mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-20 21:01:06 +08:00
Merge branch 'release/v2026.06'
This commit is contained in:
2
.github/workflows/format-check.yml
vendored
2
.github/workflows/format-check.yml
vendored
@@ -14,6 +14,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
142
TRANSLATION.md
142
TRANSLATION.md
@@ -6,30 +6,39 @@ This document shows the translation status of each locale file in the repository
|
||||
|
||||
### 
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in de_DE.axaml</summary>
|
||||
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.CommitMessageTextBox.Column
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.GotoRevisionSelector
|
||||
- Text.Hotkeys.Repo.GoToChild
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.StashCM.ApplyFileChanges
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Path
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in es_ES.axaml</summary>
|
||||
|
||||
- Text.GotoRevisionSelector
|
||||
- Text.Hotkeys.Repo.GoToChild
|
||||
- Text.StashCM.ApplyFileChanges
|
||||
- Text.Preferences.General.Use24Hours
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in fr_FR.axaml</summary>
|
||||
@@ -44,10 +53,15 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ChangeCM.MergeExternal
|
||||
- Text.ChangeCM.ResetFileTo
|
||||
- Text.Checkout.WarnUpdatingSubmodules
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.CommitMessageTextBox.Column
|
||||
- Text.CommitMessageTextBox.Placeholder
|
||||
- Text.Compare.WithHead
|
||||
- Text.Configure.Git.AskBeforeAutoUpdatingSubmodules
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.EditBranchDescription
|
||||
- Text.EditBranchDescription.Target
|
||||
- Text.FileCM.CustomAction
|
||||
@@ -58,6 +72,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Global.Zoom
|
||||
- Text.Hotkeys.Repo.GoToChild
|
||||
- Text.Hotkeys.Repo.GoToParent
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.MergeConflictEditor.AcceptBoth.MineFirst
|
||||
- Text.MergeConflictEditor.AcceptBoth.TheirsFirst
|
||||
- Text.MergeConflictEditor.UseBoth
|
||||
@@ -82,6 +98,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Preferences.DiffMerge.DiffArgs.Tip
|
||||
- Text.Preferences.DiffMerge.MergeArgs
|
||||
- Text.Preferences.DiffMerge.MergeArgs.Tip
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.Preferences.Shell.Args
|
||||
- Text.Preferences.Shell.Args.Tip
|
||||
- Text.Repository.OpenAsFolder
|
||||
@@ -97,11 +114,14 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.TagCM.CompareWithHead
|
||||
- Text.WorkingCopy.Conflicts.Merge
|
||||
- Text.WorkingCopy.Conflicts.MergeExternal
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Path
|
||||
- Text.Yes
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in id_ID.axaml</summary>
|
||||
@@ -120,6 +140,10 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ChangeCM.MergeExternal
|
||||
- Text.ChangeCM.ResetFileTo
|
||||
- Text.Checkout.WarnUpdatingSubmodules
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.CommitCM.Drop
|
||||
- Text.CommitMessageTextBox.Column
|
||||
- Text.CommitMessageTextBox.Placeholder
|
||||
@@ -128,6 +152,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Configure.Git.AskBeforeAutoUpdatingSubmodules
|
||||
- Text.Configure.Git.ConventionalTypesOverride
|
||||
- Text.ConfigureCustomActionControls.StringValue.Tip
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.DropHead
|
||||
- Text.DropHead.Commit
|
||||
- Text.DropHead.NewHead
|
||||
@@ -144,6 +169,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Repo.GoToChild
|
||||
- Text.Hotkeys.Repo.GoToParent
|
||||
- Text.Hotkeys.Repo.OpenCommandPalette
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.Launcher.Commands
|
||||
- Text.Launcher.OpenRepository
|
||||
- Text.MergeConflictEditor.AcceptBoth.MineFirst
|
||||
@@ -172,6 +199,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Preferences.DiffMerge.DiffArgs.Tip
|
||||
- Text.Preferences.DiffMerge.MergeArgs
|
||||
- Text.Preferences.DiffMerge.MergeArgs.Tip
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.Preferences.Shell.Args
|
||||
- Text.Preferences.Shell.Args.Tip
|
||||
- Text.PushToNewBranch
|
||||
@@ -189,31 +217,62 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.TagCM.CompareWithHead
|
||||
- Text.WorkingCopy.Conflicts.Merge
|
||||
- Text.WorkingCopy.Conflicts.MergeExternal
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Path
|
||||
- Text.Yes
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in it_IT.axaml</summary>
|
||||
|
||||
- Text.ChangeCM.ResetFileTo
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.CommitMessageTextBox.Column
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.GotoRevisionSelector
|
||||
- Text.Histories.Header.DateTime
|
||||
- Text.Histories.ShowColumns
|
||||
- Text.Hotkeys.Repo.GoToChild
|
||||
- Text.Hotkeys.Repo.GoToParent
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.SelfUpdate.CurrentVersion
|
||||
- Text.SelfUpdate.ReleaseDate
|
||||
- Text.StashCM.ApplyFileChanges
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Path
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
### 
|
||||
<details>
|
||||
<summary>Missing keys in ja_JP.axaml</summary>
|
||||
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Path
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in ko_KR.axaml</summary>
|
||||
@@ -232,12 +291,17 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ChangeCM.MergeExternal
|
||||
- Text.ChangeCM.ResetFileTo
|
||||
- Text.Checkout.WarnUpdatingSubmodules
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.CommitMessageTextBox.Column
|
||||
- Text.CommitMessageTextBox.Placeholder
|
||||
- Text.Compare.WithHead
|
||||
- Text.Configure.Git.AskBeforeAutoUpdatingSubmodules
|
||||
- Text.Configure.Git.ConventionalTypesOverride
|
||||
- Text.ConfigureCustomActionControls.StringValue.Tip
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.EditBranchDescription
|
||||
- Text.EditBranchDescription.Target
|
||||
- Text.FileCM.CustomAction
|
||||
@@ -251,6 +315,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Repo.GoToChild
|
||||
- Text.Hotkeys.Repo.GoToParent
|
||||
- Text.Hotkeys.Repo.OpenCommandPalette
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.Launcher.Commands
|
||||
- Text.Launcher.OpenRepository
|
||||
- Text.MergeConflictEditor.AcceptBoth.MineFirst
|
||||
@@ -280,6 +346,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Preferences.DiffMerge.DiffArgs.Tip
|
||||
- Text.Preferences.DiffMerge.MergeArgs
|
||||
- Text.Preferences.DiffMerge.MergeArgs.Tip
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.Preferences.Shell.Args
|
||||
- Text.Preferences.Shell.Args.Tip
|
||||
- Text.PushToNewBranch
|
||||
@@ -298,11 +365,14 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.TagCM.CompareWithHead
|
||||
- Text.WorkingCopy.Conflicts.Merge
|
||||
- Text.WorkingCopy.Conflicts.MergeExternal
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Path
|
||||
- Text.Yes
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in pt_BR.axaml</summary>
|
||||
@@ -325,6 +395,10 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Checkout.WithFastForward
|
||||
- Text.Checkout.WithFastForward.Upstream
|
||||
- Text.Clone.RecurseSubmodules
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.CommitCM.CopyAuthor
|
||||
- Text.CommitCM.CopyCommitMessage
|
||||
- Text.CommitCM.CopyCommitter
|
||||
@@ -385,6 +459,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ConfirmEmptyCommit.Continue
|
||||
- Text.ConfirmEmptyCommit.NoLocalChanges
|
||||
- Text.ConfirmEmptyCommit.StageAllThenCommit
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.ConfirmEmptyCommit.WithLocalChanges
|
||||
- Text.ConfirmRestart.Title
|
||||
- Text.ConfirmRestart.Message
|
||||
@@ -438,6 +513,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Repo.GoToParent
|
||||
- Text.Hotkeys.Repo.OpenCommandPalette
|
||||
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.InProgress.CherryPick.Head
|
||||
- Text.InProgress.Merge.Operating
|
||||
- Text.InProgress.Rebase.StoppedAt
|
||||
@@ -492,6 +569,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Preferences.General.ShowChangesTabInCommitDetailByDefault
|
||||
- Text.Preferences.General.ShowChildren
|
||||
- Text.Preferences.General.ShowTagsInGraph
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.Preferences.General.UseGitHubStyleAvatar
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
- Text.Preferences.Git.SSLVerify
|
||||
@@ -600,23 +678,31 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.WorkingCopy.SignOff
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Open
|
||||
- Text.Worktree.Path
|
||||
- Text.Yes
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in ru_RU.axaml</summary>
|
||||
|
||||
- Text.GotoRevisionSelector
|
||||
- Text.Hotkeys.Repo.GoToChild
|
||||
- Text.StashCM.ApplyFileChanges
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.Preferences.General.Use24Hours
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in ta_IN.axaml</summary>
|
||||
@@ -667,6 +753,10 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Checkout.WarnUpdatingSubmodules
|
||||
- Text.Checkout.WithFastForward
|
||||
- Text.Checkout.WithFastForward.Upstream
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.CommitCM.CopyAuthor
|
||||
- Text.CommitCM.CopyCommitMessage
|
||||
- Text.CommitCM.CopyCommitter
|
||||
@@ -719,6 +809,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ConfirmEmptyCommit.Continue
|
||||
- Text.ConfirmEmptyCommit.NoLocalChanges
|
||||
- Text.ConfirmEmptyCommit.StageAllThenCommit
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.ConfirmEmptyCommit.WithLocalChanges
|
||||
- Text.ConfirmRestart.Title
|
||||
- Text.ConfirmRestart.Message
|
||||
@@ -763,6 +854,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Repo.GoToParent
|
||||
- Text.Hotkeys.Repo.OpenCommandPalette
|
||||
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.InteractiveRebase.ReorderTip
|
||||
- Text.Launcher.Commands
|
||||
- Text.Launcher.OpenRepository
|
||||
@@ -803,6 +896,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.General.ShowChangesTabInCommitDetailByDefault
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.Preferences.General.UseGitHubStyleAvatar
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
- Text.Preferences.Git.UseLibsecret
|
||||
@@ -892,12 +986,15 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.WorkingCopy.Conflicts.UseTheirs
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Open
|
||||
- Text.Worktree.Path
|
||||
- Text.Yes
|
||||
|
||||
</details>
|
||||
|
||||
### 
|
||||
### 
|
||||
|
||||
<details>
|
||||
<summary>Missing keys in uk_UA.axaml</summary>
|
||||
@@ -948,6 +1045,10 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Checkout.WarnUpdatingSubmodules
|
||||
- Text.Checkout.WithFastForward
|
||||
- Text.Checkout.WithFastForward.Upstream
|
||||
- Text.CommandPalette.Branches
|
||||
- Text.CommandPalette.BranchesAndTags
|
||||
- Text.CommandPalette.RepositoryActions
|
||||
- Text.CommandPalette.RevisionFiles
|
||||
- Text.CommitCM.CopyAuthor
|
||||
- Text.CommitCM.CopyCommitMessage
|
||||
- Text.CommitCM.CopyCommitter
|
||||
@@ -997,6 +1098,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.ConfigureCustomActionControls.StringValue.Tip
|
||||
- Text.ConfigureCustomActionControls.Type
|
||||
- Text.ConfigureWorkspace.Name
|
||||
- Text.ConfirmEmptyCommit.StageSelectedThenCommit
|
||||
- Text.ConfirmRestart.Title
|
||||
- Text.ConfirmRestart.Message
|
||||
- Text.CreateBranch.OverwriteExisting
|
||||
@@ -1040,6 +1142,8 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Hotkeys.Repo.GoToParent
|
||||
- Text.Hotkeys.Repo.OpenCommandPalette
|
||||
- Text.Hotkeys.TextEditor.OpenExternalMergeTool
|
||||
- Text.Init.CommandTip
|
||||
- Text.Init.ErrorMessageTip
|
||||
- Text.InteractiveRebase.ReorderTip
|
||||
- Text.Launcher.Commands
|
||||
- Text.Launcher.OpenRepository
|
||||
@@ -1080,6 +1184,7 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.Preferences.General.EnableCompactFolders
|
||||
- Text.Preferences.General.ShowChangesPageByDefault
|
||||
- Text.Preferences.General.ShowChangesTabInCommitDetailByDefault
|
||||
- Text.Preferences.General.Use24Hours
|
||||
- Text.Preferences.General.UseGitHubStyleAvatar
|
||||
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
|
||||
- Text.Preferences.Git.UseLibsecret
|
||||
@@ -1165,7 +1270,10 @@ This document shows the translation status of each locale file in the repository
|
||||
- Text.WorkingCopy.Conflicts.MergeExternal
|
||||
- Text.WorkingCopy.NoVerify
|
||||
- Text.WorkingCopy.ResetAuthor
|
||||
- Text.Worktree.Branch
|
||||
- Text.Worktree.Head
|
||||
- Text.Worktree.Open
|
||||
- Text.Worktree.Path
|
||||
- Text.Yes
|
||||
|
||||
</details>
|
||||
|
||||
Submodule depends/AvaloniaEdit updated: 80222a80b3...87e83c5c0e
@@ -57,10 +57,5 @@ namespace SourceGit
|
||||
// Ignore exceptions.
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetRelativePath(this DirectoryInfo dir, string fullpath)
|
||||
{
|
||||
return fullpath.Substring(dir.FullName.Length).TrimStart(Path.DirectorySeparatorChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,13 +208,14 @@ namespace SourceGit
|
||||
return false;
|
||||
}
|
||||
|
||||
public static async Task<Models.ConfirmEmptyCommitResult> AskConfirmEmptyCommitAsync(bool hasLocalChanges)
|
||||
public static async Task<Models.ConfirmEmptyCommitResult> AskConfirmEmptyCommitAsync(bool hasLocalChanges, bool hasSelectedUnstaged)
|
||||
{
|
||||
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;
|
||||
confirm.BtnStageSelectedAndCommit.IsVisible = hasSelectedUnstaged;
|
||||
return await confirm.ShowDialog<Models.ConfirmEmptyCommitResult>(owner);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ namespace SourceGit.Commands
|
||||
{
|
||||
public partial class CompareRevisions : Command
|
||||
{
|
||||
[GeneratedRegex(@"^([MADC])\s+(.+)$")]
|
||||
[GeneratedRegex(@"^([MAD])\s+(.+)$")]
|
||||
private static partial Regex REG_FORMAT();
|
||||
[GeneratedRegex(@"^R[0-9]{0,4}\s+(.+)$")]
|
||||
[GeneratedRegex(@"^([CR])[0-9]{0,4}\s+(.+)$")]
|
||||
private static partial Regex REG_RENAME_FORMAT();
|
||||
|
||||
public CompareRevisions(string repo, string start, string end)
|
||||
@@ -47,8 +47,9 @@ namespace SourceGit.Commands
|
||||
match = REG_RENAME_FORMAT().Match(line);
|
||||
if (match.Success)
|
||||
{
|
||||
var renamed = new Models.Change() { Path = match.Groups[1].Value };
|
||||
renamed.Set(Models.ChangeState.Renamed);
|
||||
var type = match.Groups[1].Value;
|
||||
var renamed = new Models.Change() { Path = match.Groups[2].Value };
|
||||
renamed.Set(type == "R" ? Models.ChangeState.Renamed : Models.ChangeState.Copied);
|
||||
changes.Add(renamed);
|
||||
}
|
||||
|
||||
@@ -72,10 +73,6 @@ namespace SourceGit.Commands
|
||||
change.Set(Models.ChangeState.Deleted);
|
||||
changes.Add(change);
|
||||
break;
|
||||
case 'C':
|
||||
change.Set(Models.ChangeState.Copied);
|
||||
changes.Add(change);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
96
src/Commands/QueryFileHistory.cs
Normal file
96
src/Commands/QueryFileHistory.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Commands
|
||||
{
|
||||
public partial class QueryFileHistory : Command
|
||||
{
|
||||
[GeneratedRegex(@"^([MAD])\s+(.+)$")]
|
||||
private static partial Regex REG_FORMAT();
|
||||
[GeneratedRegex(@"^([CR])[0-9]{0,4}\s+(.+)$")]
|
||||
private static partial Regex REG_RENAME_FORMAT();
|
||||
|
||||
public QueryFileHistory(string repo, string path, string head)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
RaiseError = false;
|
||||
|
||||
var builder = new StringBuilder();
|
||||
builder.Append("log --no-show-signature --date-order -n 10000 --decorate=no --format=\"@%H%x00%P%x00%aN±%aE%x00%at%x00%s\" --follow --name-status ");
|
||||
if (!string.IsNullOrEmpty(head))
|
||||
builder.Append(head).Append(" ");
|
||||
builder.Append("-- ").Append(path.Quoted());
|
||||
|
||||
Args = builder.ToString();
|
||||
}
|
||||
|
||||
public async Task<List<Models.FileVersion>> GetResultAsync()
|
||||
{
|
||||
var versions = new List<Models.FileVersion>();
|
||||
var rs = await ReadToEndAsync().ConfigureAwait(false);
|
||||
if (!rs.IsSuccess)
|
||||
return versions;
|
||||
|
||||
var lines = rs.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
|
||||
if (lines.Length == 0)
|
||||
return versions;
|
||||
|
||||
Models.FileVersion last = null;
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line.StartsWith('@'))
|
||||
{
|
||||
var parts = line.Split('\0');
|
||||
if (parts.Length != 5)
|
||||
continue;
|
||||
|
||||
last = new Models.FileVersion();
|
||||
last.SHA = parts[0].Substring(1);
|
||||
last.HasParent = !string.IsNullOrEmpty(parts[1]);
|
||||
last.Author = Models.User.FindOrAdd(parts[2]);
|
||||
last.AuthorTime = ulong.Parse(parts[3]);
|
||||
last.Subject = parts[4];
|
||||
versions.Add(last);
|
||||
}
|
||||
else if (last != null)
|
||||
{
|
||||
var match = REG_FORMAT().Match(line);
|
||||
if (!match.Success)
|
||||
{
|
||||
match = REG_RENAME_FORMAT().Match(line);
|
||||
if (match.Success)
|
||||
{
|
||||
var type = match.Groups[1].Value;
|
||||
last.Change.Path = match.Groups[2].Value;
|
||||
last.Change.Set(type == "R" ? Models.ChangeState.Renamed : Models.ChangeState.Copied);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
last.Change.Path = match.Groups[2].Value;
|
||||
|
||||
var status = match.Groups[1].Value;
|
||||
switch (status[0])
|
||||
{
|
||||
case 'M':
|
||||
last.Change.Set(Models.ChangeState.Modified);
|
||||
break;
|
||||
case 'A':
|
||||
last.Change.Set(Models.ChangeState.Added);
|
||||
break;
|
||||
case 'D':
|
||||
last.Change.Set(Models.ChangeState.Deleted);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return versions;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,9 @@ namespace SourceGit.Commands
|
||||
{
|
||||
public partial class QueryStagedChangesWithAmend : Command
|
||||
{
|
||||
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ACDMT])\d{0,6}\t(.*)$")]
|
||||
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([ADMT])\d{0,6}\t(.*)$")]
|
||||
private static partial Regex REG_FORMAT1();
|
||||
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} R\d{0,6}\t(.*\t.*)$")]
|
||||
[GeneratedRegex(@"^:[\d]{6} ([\d]{6}) ([0-9a-f]{40}) [0-9a-f]{40} ([RC])\d{0,6}\t(.*\t.*)$")]
|
||||
private static partial Regex REG_FORMAT2();
|
||||
|
||||
public QueryStagedChangesWithAmend(string repo, string parent)
|
||||
@@ -34,7 +34,7 @@ namespace SourceGit.Commands
|
||||
{
|
||||
var change = new Models.Change()
|
||||
{
|
||||
Path = match.Groups[3].Value,
|
||||
Path = match.Groups[4].Value,
|
||||
DataForAmend = new Models.ChangeDataForAmend()
|
||||
{
|
||||
FileMode = match.Groups[1].Value,
|
||||
@@ -42,7 +42,8 @@ namespace SourceGit.Commands
|
||||
ParentSHA = _parent,
|
||||
},
|
||||
};
|
||||
change.Set(Models.ChangeState.Renamed);
|
||||
var type = match.Groups[3].Value;
|
||||
change.Set(type == "R" ? Models.ChangeState.Renamed : Models.ChangeState.Copied);
|
||||
changes.Add(change);
|
||||
continue;
|
||||
}
|
||||
@@ -67,9 +68,6 @@ namespace SourceGit.Commands
|
||||
case "A":
|
||||
change.Set(Models.ChangeState.Added);
|
||||
break;
|
||||
case "C":
|
||||
change.Set(Models.ChangeState.Copied);
|
||||
break;
|
||||
case "D":
|
||||
change.Set(Models.ChangeState.Deleted);
|
||||
break;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"reset HEAD --pathspec-from-file={pathspec.Quoted()}";
|
||||
Args = $"reset --pathspec-from-file={pathspec.Quoted()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -29,7 +28,6 @@ namespace SourceGit.Commands
|
||||
if (line.StartsWith("worktree ", StringComparison.Ordinal))
|
||||
{
|
||||
last = new Models.Worktree() { FullPath = line.Substring(9).Trim() };
|
||||
last.RelativePath = Path.GetRelativePath(WorkingDirectory, last.FullPath);
|
||||
worktrees.Add(last);
|
||||
continue;
|
||||
}
|
||||
@@ -39,8 +37,7 @@ namespace SourceGit.Commands
|
||||
|
||||
if (line.StartsWith("bare", StringComparison.Ordinal))
|
||||
{
|
||||
worktrees.Remove(last);
|
||||
last = null;
|
||||
last.IsBare = true;
|
||||
}
|
||||
else if (line.StartsWith("HEAD ", StringComparison.Ordinal))
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace SourceGit.Converters
|
||||
public static class InteractiveRebaseActionConverters
|
||||
{
|
||||
public static readonly FuncValueConverter<Models.InteractiveRebaseAction, IBrush> ToIconBrush =
|
||||
new FuncValueConverter<Models.InteractiveRebaseAction, IBrush>(v =>
|
||||
new(v =>
|
||||
{
|
||||
return v switch
|
||||
{
|
||||
@@ -20,6 +20,12 @@ namespace SourceGit.Converters
|
||||
});
|
||||
|
||||
public static readonly FuncValueConverter<Models.InteractiveRebaseAction, string> ToName =
|
||||
new FuncValueConverter<Models.InteractiveRebaseAction, string>(v => v.ToString());
|
||||
new(v => v.ToString());
|
||||
|
||||
public static readonly FuncValueConverter<Models.InteractiveRebaseAction, bool> IsDrop =
|
||||
new(v => v == Models.InteractiveRebaseAction.Drop);
|
||||
|
||||
public static readonly FuncValueConverter<Models.InteractiveRebaseAction, double> ToOpacity =
|
||||
new(v => v > Models.InteractiveRebaseAction.Reword ? 0.65 : 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
@@ -10,7 +9,6 @@ namespace SourceGit.Models
|
||||
public string File { get; set; } = string.Empty;
|
||||
public string Author { get; set; } = string.Empty;
|
||||
public ulong Timestamp { get; set; } = 0;
|
||||
public string Time => DateTime.UnixEpoch.AddSeconds(Timestamp).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
|
||||
}
|
||||
|
||||
public class BlameData
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
Index = index;
|
||||
WorkTree = workTree;
|
||||
|
||||
if (index == ChangeState.Renamed || workTree == ChangeState.Renamed)
|
||||
if (index == ChangeState.Renamed || index == ChangeState.Copied || workTree == ChangeState.Renamed)
|
||||
{
|
||||
var parts = Path.Split('\t', 2);
|
||||
if (parts.Length < 2)
|
||||
|
||||
@@ -30,11 +30,6 @@ namespace SourceGit.Models
|
||||
public int Color { get; set; } = 0;
|
||||
public double LeftMargin { get; set; } = 0;
|
||||
|
||||
public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
|
||||
public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
|
||||
public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
|
||||
public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly);
|
||||
|
||||
public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime;
|
||||
public bool IsCurrentHead => Decorators.Find(x => x.Type is DecoratorType.CurrentBranchHead or DecoratorType.CurrentCommitHead) != null;
|
||||
public bool HasDecorators => Decorators.Count > 0;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
public enum ConfirmEmptyCommitResult
|
||||
{
|
||||
Cancel = 0,
|
||||
StageSelectedAndCommit,
|
||||
StageAllAndCommit,
|
||||
CreateEmptyCommit,
|
||||
}
|
||||
|
||||
@@ -5,19 +5,20 @@ namespace SourceGit.Models
|
||||
{
|
||||
public class DateTimeFormat
|
||||
{
|
||||
public string DateOnly { get; set; }
|
||||
public string DateTime { get; set; }
|
||||
|
||||
public string Example
|
||||
public static readonly List<DateTimeFormat> Supported = new List<DateTimeFormat>
|
||||
{
|
||||
get => _example.ToString(DateTime);
|
||||
}
|
||||
|
||||
public DateTimeFormat(string dateOnly, string dateTime)
|
||||
{
|
||||
DateOnly = dateOnly;
|
||||
DateTime = dateTime;
|
||||
}
|
||||
new("yyyy/MM/dd"),
|
||||
new("yyyy.MM.dd"),
|
||||
new("yyyy-MM-dd"),
|
||||
new("MM/dd/yyyy"),
|
||||
new("MM.dd.yyyy"),
|
||||
new("MM-dd-yyyy"),
|
||||
new("dd/MM/yyyy"),
|
||||
new("dd.MM.yyyy"),
|
||||
new("dd-MM-yyyy"),
|
||||
new("MMM d yyyy"),
|
||||
new("d MMM yyyy"),
|
||||
};
|
||||
|
||||
public static int ActiveIndex
|
||||
{
|
||||
@@ -25,26 +26,41 @@ namespace SourceGit.Models
|
||||
set;
|
||||
} = 0;
|
||||
|
||||
public static DateTimeFormat Active
|
||||
public static bool Use24Hours
|
||||
{
|
||||
get => Supported[ActiveIndex];
|
||||
get;
|
||||
set;
|
||||
} = true;
|
||||
|
||||
public string DateFormat
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public static readonly List<DateTimeFormat> Supported = new List<DateTimeFormat>
|
||||
public string Example
|
||||
{
|
||||
new DateTimeFormat("yyyy/MM/dd", "yyyy/MM/dd, HH:mm:ss"),
|
||||
new DateTimeFormat("yyyy.MM.dd", "yyyy.MM.dd, HH:mm:ss"),
|
||||
new DateTimeFormat("yyyy-MM-dd", "yyyy-MM-dd, HH:mm:ss"),
|
||||
new DateTimeFormat("MM/dd/yyyy", "MM/dd/yyyy, HH:mm:ss"),
|
||||
new DateTimeFormat("MM.dd.yyyy", "MM.dd.yyyy, HH:mm:ss"),
|
||||
new DateTimeFormat("MM-dd-yyyy", "MM-dd-yyyy, HH:mm:ss"),
|
||||
new DateTimeFormat("dd/MM/yyyy", "dd/MM/yyyy, HH:mm:ss"),
|
||||
new DateTimeFormat("dd.MM.yyyy", "dd.MM.yyyy, HH:mm:ss"),
|
||||
new DateTimeFormat("dd-MM-yyyy", "dd-MM-yyyy, HH:mm:ss"),
|
||||
new DateTimeFormat("MMM d yyyy", "MMM d yyyy, HH:mm:ss"),
|
||||
new DateTimeFormat("d MMM yyyy", "d MMM yyyy, HH:mm:ss"),
|
||||
};
|
||||
get => DateTime.Now.ToString(DateFormat);
|
||||
}
|
||||
|
||||
private static readonly DateTime _example = new DateTime(2025, 1, 31, 8, 0, 0, DateTimeKind.Local);
|
||||
public DateTimeFormat(string date)
|
||||
{
|
||||
DateFormat = date;
|
||||
}
|
||||
|
||||
public static string Format(ulong timestamp, bool dateOnly = false)
|
||||
{
|
||||
var localTime = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime();
|
||||
return Format(localTime, dateOnly);
|
||||
}
|
||||
|
||||
public static string Format(DateTime localTime, bool dateOnly = false)
|
||||
{
|
||||
var actived = Supported[ActiveIndex];
|
||||
if (dateOnly)
|
||||
return localTime.ToString(actived.DateFormat);
|
||||
|
||||
var format = Use24Hours ? $"{actived.DateFormat} HH:mm:ss" : $"{actived.DateFormat} hh:mm:ss tt";
|
||||
return localTime.ToString(format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SourceGit.Models
|
||||
@@ -79,6 +80,63 @@ namespace SourceGit.Models
|
||||
_path = file;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to diff in `FileHistory`
|
||||
/// </summary>
|
||||
/// <param name="ver"></param>
|
||||
public DiffOption(FileVersion ver)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ver.OriginalPath))
|
||||
{
|
||||
_revisions.Add(ver.HasParent ? $"{ver.SHA}^" : Commit.EmptyTreeSHA1);
|
||||
_revisions.Add(ver.SHA);
|
||||
_path = ver.Path;
|
||||
}
|
||||
else
|
||||
{
|
||||
_revisions.Add($"{ver.SHA}^:{ver.OriginalPath.Quoted()}");
|
||||
_revisions.Add($"{ver.SHA}:{ver.Path.Quoted()}");
|
||||
_path = ver.Path;
|
||||
_orgPath = ver.Change.OriginalPath;
|
||||
_ignorePaths = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to diff two revisions in `FileHistory`
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
public DiffOption(FileVersion start, FileVersion end)
|
||||
{
|
||||
if (start.Change.Index == ChangeState.Deleted)
|
||||
{
|
||||
_revisions.Add(Commit.EmptyTreeSHA1);
|
||||
_revisions.Add(end.SHA);
|
||||
_path = end.Path;
|
||||
}
|
||||
else if (end.Change.Index == ChangeState.Deleted)
|
||||
{
|
||||
_revisions.Add(start.SHA);
|
||||
_revisions.Add(Commit.EmptyTreeSHA1);
|
||||
_path = start.Path;
|
||||
}
|
||||
else if (!end.Path.Equals(start.Path, StringComparison.Ordinal))
|
||||
{
|
||||
_revisions.Add($"{start.SHA}:{start.Path.Quoted()}");
|
||||
_revisions.Add($"{end.SHA}:{end.Path.Quoted()}");
|
||||
_path = end.Path;
|
||||
_orgPath = start.Path;
|
||||
_ignorePaths = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_revisions.Add(start.SHA);
|
||||
_revisions.Add(end.SHA);
|
||||
_path = start.Path;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to show differences between two revisions.
|
||||
/// </summary>
|
||||
@@ -104,6 +162,9 @@ namespace SourceGit.Models
|
||||
foreach (var r in _revisions)
|
||||
builder.Append($"{r} ");
|
||||
|
||||
if (_ignorePaths)
|
||||
return builder.ToString();
|
||||
|
||||
builder.Append("-- ");
|
||||
if (!string.IsNullOrEmpty(_orgPath))
|
||||
builder.Append($"{_orgPath.Quoted()} ");
|
||||
@@ -118,5 +179,6 @@ namespace SourceGit.Models
|
||||
private readonly string _orgPath = string.Empty;
|
||||
private readonly string _extra = string.Empty;
|
||||
private readonly List<string> _revisions = [];
|
||||
private readonly bool _ignorePaths = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,9 +124,9 @@ namespace SourceGit.Models
|
||||
continue;
|
||||
|
||||
if (i >= selection.StartLine - 1 && i < selection.EndLine)
|
||||
writer.WriteLine($"+{line.Content}");
|
||||
WriteLine(writer, '+', line);
|
||||
else
|
||||
writer.WriteLine($" {line.Content}");
|
||||
WriteLine(writer, ' ', line);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -137,11 +137,10 @@ namespace SourceGit.Models
|
||||
var line = Lines[i];
|
||||
if (line.Type != TextDiffLineType.Added)
|
||||
continue;
|
||||
writer.WriteLine($"+{line.Content}");
|
||||
WriteLine(writer, '+', line);
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteLine("\\ No newline at end of file");
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
@@ -255,7 +254,8 @@ namespace SourceGit.Models
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteLine($" {tail}");
|
||||
if (!string.IsNullOrEmpty(tail))
|
||||
writer.WriteLine($" {tail}");
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
@@ -406,7 +406,8 @@ namespace SourceGit.Models
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteLine($" {tail}");
|
||||
if (!string.IsNullOrEmpty(tail))
|
||||
writer.WriteLine($" {tail}");
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
|
||||
@@ -230,10 +230,14 @@ namespace SourceGit.Models
|
||||
return null;
|
||||
|
||||
var options = new List<ExternalTool.LaunchOption>();
|
||||
var prefixLen = root.FullName.Length;
|
||||
root.WalkFiles(f =>
|
||||
{
|
||||
if (f.EndsWith(".code-workspace", StringComparison.OrdinalIgnoreCase))
|
||||
options.Add(new(root.GetRelativePath(f), f.Quoted()));
|
||||
{
|
||||
var display = f.Substring(prefixLen).TrimStart(Path.DirectorySeparatorChar);
|
||||
options.Add(new(display, f.Quoted()));
|
||||
}
|
||||
}, 2);
|
||||
return options;
|
||||
}
|
||||
|
||||
14
src/Models/FileVersion.cs
Normal file
14
src/Models/FileVersion.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public class FileVersion
|
||||
{
|
||||
public string SHA { get; set; } = string.Empty;
|
||||
public bool HasParent { get; set; } = false;
|
||||
public User Author { get; set; } = User.Invalid;
|
||||
public ulong AuthorTime { get; set; } = 0;
|
||||
public string Subject { get; set; } = string.Empty;
|
||||
public Change Change { get; set; } = new();
|
||||
public string Path => Change.Path;
|
||||
public string OriginalPath => Change.OriginalPath;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace SourceGit.Models
|
||||
public bool IsNewVersion => CurrentVersion.CompareTo(new System.Version(TagName.Substring(1))) < 0;
|
||||
|
||||
[JsonIgnore]
|
||||
public string ReleaseDateStr => PublishedAt.ToString(DateTimeFormat.Active.DateOnly);
|
||||
public string ReleaseDateStr => DateTimeFormat.Format(PublishedAt, true);
|
||||
|
||||
public Version()
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
@@ -10,24 +9,6 @@ namespace SourceGit.Models
|
||||
public List<string> Parents { get; set; } = [];
|
||||
public ulong Time { get; set; } = 0;
|
||||
public string Message { get; set; } = "";
|
||||
|
||||
public string Subject
|
||||
{
|
||||
get
|
||||
{
|
||||
return Message.Split('\n', 2)[0].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
public string TimeStr
|
||||
{
|
||||
get
|
||||
{
|
||||
return DateTime.UnixEpoch
|
||||
.AddSeconds(Time)
|
||||
.ToLocalTime()
|
||||
.ToString(DateTimeFormat.Active.DateTime);
|
||||
}
|
||||
}
|
||||
public string Subject => Message.Split('\n', 2)[0].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
|
||||
namespace SourceGit.Models
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public enum TagSortMode
|
||||
{
|
||||
@@ -16,10 +14,5 @@ namespace SourceGit.Models
|
||||
public User Creator { get; set; } = null;
|
||||
public ulong CreatorDate { get; set; } = 0;
|
||||
public string Message { get; set; } = string.Empty;
|
||||
|
||||
public string CreatorDateStr
|
||||
{
|
||||
get => DateTime.UnixEpoch.AddSeconds(CreatorDate).ToLocalTime().ToString(DateTimeFormat.Active.DateTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +1,12 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public class Worktree : ObservableObject
|
||||
public class Worktree
|
||||
{
|
||||
public string Branch { get; set; } = string.Empty;
|
||||
public string FullPath { get; set; } = string.Empty;
|
||||
public string RelativePath { get; set; } = string.Empty;
|
||||
public string Head { get; set; } = string.Empty;
|
||||
public bool IsBare { get; set; } = false;
|
||||
public bool IsDetached { get; set; } = false;
|
||||
|
||||
public bool IsLocked
|
||||
{
|
||||
get => _isLocked;
|
||||
set => SetProperty(ref _isLocked, value);
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsDetached)
|
||||
return $"detached HEAD at {Head.AsSpan(10)}";
|
||||
|
||||
if (Branch.StartsWith("refs/heads/", StringComparison.Ordinal))
|
||||
return Branch.Substring(11);
|
||||
|
||||
if (Branch.StartsWith("refs/remotes/", StringComparison.Ordinal))
|
||||
return Branch.Substring(13);
|
||||
|
||||
return Branch;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isLocked = false;
|
||||
public bool IsLocked { get; set; } = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,11 +234,15 @@ namespace SourceGit.Native
|
||||
return null;
|
||||
|
||||
var options = new List<Models.ExternalTool.LaunchOption>();
|
||||
var prefixLen = root.FullName.Length;
|
||||
root.WalkFiles(f =>
|
||||
{
|
||||
if (f.EndsWith(".sln", StringComparison.OrdinalIgnoreCase) ||
|
||||
f.EndsWith(".slnx", StringComparison.OrdinalIgnoreCase))
|
||||
options.Add(new(root.GetRelativePath(f), f.Quoted()));
|
||||
{
|
||||
var display = f.Substring(prefixLen).TrimStart(Path.DirectorySeparatorChar);
|
||||
options.Add(new(display, f.Quoted()));
|
||||
}
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -134,6 +134,10 @@
|
||||
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">Repository URL:</x:String>
|
||||
<x:String x:Key="Text.Close" xml:space="preserve">CLOSE</x:String>
|
||||
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Editor</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.Branches" xml:space="preserve">Branches</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.BranchesAndTags" xml:space="preserve">Branches & Tags</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.RepositoryActions" xml:space="preserve">Repository Custom Actions</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.RevisionFiles" xml:space="preserve">Revision Files</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Checkout Commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">Cherry-Pick Commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">Cherry-Pick ...</x:String>
|
||||
@@ -277,7 +281,8 @@
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.Continue" xml:space="preserve">CONTINUE</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.NoLocalChanges" xml:space="preserve">Empty commit detected! Do you want to continue (--allow-empty)?</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">STAGE ALL & COMMIT</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">Empty commit detected! Do you want to continue (--allow-empty) or stage all then commit?</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageSelectedThenCommit" xml:space="preserve">STAGE SELECTED & COMMIT</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">Empty commit detected! Do you want to continue (--allow-empty) or auto-stage then commit?</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Title" xml:space="preserve">Restart Required</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Message" xml:space="preserve">You need to restart this app to apply changes.</x:String>
|
||||
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">Conventional Commit Helper</x:String>
|
||||
@@ -309,7 +314,7 @@
|
||||
<x:String x:Key="Text.CreateTag.Name" xml:space="preserve">Tag Name:</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">Recommended format: v1.0.0-alpha</x:String>
|
||||
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">Push to all remotes after created</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Title" xml:space="preserve">Create New Tag</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Title" xml:space="preserve">Create Tag</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">Kind:</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">annotated</x:String>
|
||||
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">lightweight</x:String>
|
||||
@@ -519,6 +524,8 @@
|
||||
<x:String x:Key="Text.Hunk.Stage" xml:space="preserve">Stage</x:String>
|
||||
<x:String x:Key="Text.Hunk.Unstage" xml:space="preserve">Unstage</x:String>
|
||||
<x:String x:Key="Text.Init" xml:space="preserve">Initialize Repository</x:String>
|
||||
<x:String x:Key="Text.Init.CommandTip" xml:space="preserve">Do you want to run `git init` command under this path?</x:String>
|
||||
<x:String x:Key="Text.Init.ErrorMessageTip" xml:space="preserve">Open repository failed. Reason: </x:String>
|
||||
<x:String x:Key="Text.Init.Path" xml:space="preserve">Path:</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Cherry-Pick in progress.</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick.Head" xml:space="preserve">Processing commit</x:String>
|
||||
@@ -642,6 +649,7 @@
|
||||
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Show children in the commit details</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Show tags in commit graph</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Use24Hours" xml:space="preserve">24-Hours</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.UseGitHubStyleAvatar" xml:space="preserve">Generate Github style default avatar</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Enable Auto CRLF</x:String>
|
||||
@@ -969,9 +977,12 @@
|
||||
<x:String x:Key="Text.Workspace" xml:space="preserve">WORKSPACE: </x:String>
|
||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configure Workspaces...</x:String>
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">WORKTREE</x:String>
|
||||
<x:String x:Key="Text.Worktree.Branch" xml:space="preserve">BRANCH</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Copy Path</x:String>
|
||||
<x:String x:Key="Text.Worktree.Head" xml:space="preserve">HEAD</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.Path" xml:space="preserve">PATH</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>
|
||||
<x:String x:Key="Text.Yes" xml:space="preserve">YES</x:String>
|
||||
|
||||
@@ -138,6 +138,10 @@
|
||||
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">URL del Repositorio:</x:String>
|
||||
<x:String x:Key="Text.Close" xml:space="preserve">CERRAR</x:String>
|
||||
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Editor</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.Branches" xml:space="preserve">Ramas</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.BranchesAndTags" xml:space="preserve">Ramas & Etiquetas</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.RepositoryActions" xml:space="preserve">Acciones Personalizadas del Repositorio</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.RevisionFiles" xml:space="preserve">Archivos de Revisión</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Checkout Commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">Cherry-Pick Este Commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">Cherry-Pick ...</x:String>
|
||||
@@ -281,6 +285,7 @@
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.Continue" xml:space="preserve">CONTINUAR</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.NoLocalChanges" xml:space="preserve">¡Commit vacío detectado! ¿Quieres continuar (--allow-empty)?</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">HACER STAGE A TODO & COMMIT</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageSelectedThenCommit" xml:space="preserve">STAGE LO SELECCIONADO & COMMIT</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">¡Commit vacío detectado! ¿Quieres continuar (--allow-empty) o hacer stage a todo y después commit?</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Title" xml:space="preserve">Reinicio Requerido</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Message" xml:space="preserve">Necesita reiniciar esta aplicación para aplicar los cambios.</x:String>
|
||||
@@ -473,6 +478,7 @@
|
||||
<x:String x:Key="Text.GitLFS.Remote" xml:space="preserve">Remoto:</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Track" xml:space="preserve">Seguir archivos llamados '{0}'</x:String>
|
||||
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">Seguir todos los archivos *{0}</x:String>
|
||||
<x:String x:Key="Text.GotoRevisionSelector" xml:space="preserve">Seleccionar Commit</x:String>
|
||||
<x:String x:Key="Text.Histories" xml:space="preserve">Historias</x:String>
|
||||
<x:String x:Key="Text.Histories.Header.Author" xml:space="preserve">AUTOR</x:String>
|
||||
<x:String x:Key="Text.Histories.Header.AuthorTime" xml:space="preserve">HORA DEL AUTOR</x:String>
|
||||
@@ -502,6 +508,7 @@
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">Stage todos los cambios y commit</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Fetch" xml:space="preserve">Fetch, empieza directamente</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">Modo Dashboard (Por Defecto)</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoToChild" xml:space="preserve">Ir al hijo del commit seleccionado</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoToParent" xml:space="preserve">Ir al padre del commit seleccionado</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.OpenCommandPalette" xml:space="preserve">Abrir paleta de comandos</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">Modo de búsqueda de commits</x:String>
|
||||
@@ -521,6 +528,8 @@
|
||||
<x:String x:Key="Text.Hunk.Stage" xml:space="preserve">Stage</x:String>
|
||||
<x:String x:Key="Text.Hunk.Unstage" xml:space="preserve">Unstage</x:String>
|
||||
<x:String x:Key="Text.Init" xml:space="preserve">Inicializar Repositorio</x:String>
|
||||
<x:String x:Key="Text.Init.CommandTip" xml:space="preserve">¿Quieres correr el comando `git init` en esta ruta?</x:String>
|
||||
<x:String x:Key="Text.Init.ErrorMessageTip" xml:space="preserve">Falló la apertura del repositorio. Razón: </x:String>
|
||||
<x:String x:Key="Text.Init.Path" xml:space="preserve">Ruta:</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Cherry-Pick en progreso.</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick.Head" xml:space="preserve">Procesando commit</x:String>
|
||||
@@ -853,6 +862,7 @@
|
||||
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">¡Tanto los cambios staged como los no staged de los archivos seleccionados serán stashed!</x:String>
|
||||
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Cambios Locales</x:String>
|
||||
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Aplicar</x:String>
|
||||
<x:String x:Key="Text.StashCM.ApplyFileChanges" xml:space="preserve">Aplicar Cambios</x:String>
|
||||
<x:String x:Key="Text.StashCM.CopyMessage" xml:space="preserve">Copiar Mensaje</x:String>
|
||||
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Eliminar</x:String>
|
||||
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Guardar como Parche...</x:String>
|
||||
@@ -970,9 +980,12 @@
|
||||
<x:String x:Key="Text.Workspace" xml:space="preserve">ESPACIO DE TRABAJO: </x:String>
|
||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Configura Espacios de Trabajo...</x:String>
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">WORKTREE</x:String>
|
||||
<x:String x:Key="Text.Worktree.Branch" xml:space="preserve">RAMA</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Copiar Ruta</x:String>
|
||||
<x:String x:Key="Text.Worktree.Head" xml:space="preserve">HEAD</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.Path" xml:space="preserve">RUTA</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>
|
||||
<x:String x:Key="Text.Yes" xml:space="preserve">SÍ</x:String>
|
||||
|
||||
@@ -473,6 +473,7 @@
|
||||
<x:String x:Key="Text.GitLFS.Remote" xml:space="preserve">Внешнее хранилище:</x:String>
|
||||
<x:String x:Key="Text.GitLFS.Track" xml:space="preserve">Отслеживать файлы с именем «{0}»</x:String>
|
||||
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">Отслеживать все файлы (*{0})</x:String>
|
||||
<x:String x:Key="Text.GotoRevisionSelector" xml:space="preserve">Выбрать ревизию</x:String>
|
||||
<x:String x:Key="Text.Histories" xml:space="preserve">Истории</x:String>
|
||||
<x:String x:Key="Text.Histories.Header.Author" xml:space="preserve">АВТОР</x:String>
|
||||
<x:String x:Key="Text.Histories.Header.AuthorTime" xml:space="preserve">ВРЕМЯ АВТОРА</x:String>
|
||||
@@ -502,7 +503,8 @@
|
||||
<x:String x:Key="Text.Hotkeys.Repo.CommitWithAutoStage" xml:space="preserve">Сформировать все изменения и зафиксировать</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Fetch" xml:space="preserve">Извлечь (fetch), запускается сразу</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">Режим доски (по умолчанию)</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoToParent" xml:space="preserve">Перейти к родительскому выбранной ревизии</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoToChild" xml:space="preserve">К дочернему выбранной ревизии</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.GoToParent" xml:space="preserve">К родительскому выбранной ревизии</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.OpenCommandPalette" xml:space="preserve">Открыть палитру команд</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">Режим поиска ревизий</x:String>
|
||||
<x:String x:Key="Text.Hotkeys.Repo.Pull" xml:space="preserve">Загрузить (pull), запускается сразу</x:String>
|
||||
@@ -853,6 +855,7 @@
|
||||
<x:String x:Key="Text.Stash.TipForSelectedFiles" xml:space="preserve">Сформированные так и несформированные изменения выбранных файлов будут сохранены!!!</x:String>
|
||||
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Отложить локальные изменения</x:String>
|
||||
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Принять</x:String>
|
||||
<x:String x:Key="Text.StashCM.ApplyFileChanges" xml:space="preserve">Применить изменения</x:String>
|
||||
<x:String x:Key="Text.StashCM.CopyMessage" xml:space="preserve">Копировать сообщение</x:String>
|
||||
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Отбросить</x:String>
|
||||
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Сохранить как заплатку...</x:String>
|
||||
@@ -970,9 +973,12 @@
|
||||
<x:String x:Key="Text.Workspace" xml:space="preserve">РАБОЧЕЕ ПРОСТРАНСТВО: </x:String>
|
||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">Настройка рабочего пространства...</x:String>
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">РАБОЧИЙ КАТАЛОГ</x:String>
|
||||
<x:String x:Key="Text.Worktree.Branch" xml:space="preserve">ВЕТКА</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Копировать путь</x:String>
|
||||
<x:String x:Key="Text.Worktree.Head" 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.Path" 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>
|
||||
<x:String x:Key="Text.Yes" xml:space="preserve">Да</x:String>
|
||||
|
||||
@@ -138,6 +138,10 @@
|
||||
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">远程仓库 :</x:String>
|
||||
<x:String x:Key="Text.Close" xml:space="preserve">关闭</x:String>
|
||||
<x:String x:Key="Text.CodeEditor" xml:space="preserve">提交信息编辑器</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.Branches" xml:space="preserve">分支列表</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.BranchesAndTags" xml:space="preserve">分支 & 标签</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.RepositoryActions" xml:space="preserve">自定义操作列表</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.RevisionFiles" xml:space="preserve">文件列表</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">检出此提交</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">挑选(cherry-pick)此提交</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">挑选(cherry-pick)...</x:String>
|
||||
@@ -280,8 +284,9 @@
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">启动时恢复打开的仓库</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.Continue" xml:space="preserve">确认继续</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.NoLocalChanges" xml:space="preserve">提交未包含变更文件!是否继续(--allow-empty)?</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">自动暂存并提交</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">提交未包含变更文件!是否继续(--allow-empty)或是自动暂存所有变更并提交?</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">暂存所有变更并提交</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageSelectedThenCommit" xml:space="preserve">仅暂存所选变更并提交</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">提交未包含变更文件!是否继续(--allow-empty)或是自动暂存变更并提交?</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Title" xml:space="preserve">系统提示</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Message" xml:space="preserve">程序需要重新启动,以便修改生效!</x:String>
|
||||
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">规范化提交信息生成</x:String>
|
||||
@@ -523,6 +528,8 @@
|
||||
<x:String x:Key="Text.Hunk.Stage" xml:space="preserve">暂存</x:String>
|
||||
<x:String x:Key="Text.Hunk.Unstage" xml:space="preserve">移出暂存区</x:String>
|
||||
<x:String x:Key="Text.Init" xml:space="preserve">初始化新仓库</x:String>
|
||||
<x:String x:Key="Text.Init.CommandTip" xml:space="preserve">是否在该路径下执行 `git init` 命令(初始化仓库)?</x:String>
|
||||
<x:String x:Key="Text.Init.ErrorMessageTip" xml:space="preserve">打开本地仓库失败,原因:</x:String>
|
||||
<x:String x:Key="Text.Init.Path" xml:space="preserve">路径 :</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">挑选(Cherry-Pick)操作进行中。</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick.Head" xml:space="preserve">正在处理提交</x:String>
|
||||
@@ -646,6 +653,7 @@
|
||||
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">在提交详情页中显示子提交列表</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">在提交路线图中显示标签</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">SUBJECT字数检测</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Use24Hours" xml:space="preserve">24小时制</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.UseGitHubStyleAvatar" xml:space="preserve">生成GitHub风格的默认头像</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT配置</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">自动换行转换</x:String>
|
||||
@@ -973,9 +981,12 @@
|
||||
<x:String x:Key="Text.Workspace" xml:space="preserve">工作区:</x:String>
|
||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">配置工作区...</x:String>
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">本地工作树</x:String>
|
||||
<x:String x:Key="Text.Worktree.Branch" xml:space="preserve">連結分支</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">复制工作树路径</x:String>
|
||||
<x:String x:Key="Text.Worktree.Head" 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.Path" 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>
|
||||
<x:String x:Key="Text.Yes" xml:space="preserve">好的</x:String>
|
||||
|
||||
@@ -138,6 +138,10 @@
|
||||
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">遠端存放庫:</x:String>
|
||||
<x:String x:Key="Text.Close" xml:space="preserve">關閉</x:String>
|
||||
<x:String x:Key="Text.CodeEditor" xml:space="preserve">提交訊息編輯器</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.Branches" xml:space="preserve">分支列表</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.BranchesAndTags" xml:space="preserve">分支 & 標籤</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.RepositoryActions" xml:space="preserve">自訂動作</x:String>
|
||||
<x:String x:Key="Text.CommandPalette.RevisionFiles" xml:space="preserve">檔案列表</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">簽出 (checkout) 此提交</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">揀選 (cherry-pick) 此提交</x:String>
|
||||
<x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">揀選 (cherry-pick)...</x:String>
|
||||
@@ -280,8 +284,9 @@
|
||||
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">啟動時還原上次開啟的存放庫</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.Continue" xml:space="preserve">確認繼續</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.NoLocalChanges" xml:space="preserve">未包含任何檔案變更! 您是否仍要提交 (--allow-empty)?</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">自動暫存並提交</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">未包含任何檔案變更! 您是否仍要提交 (--allow-empty) 或者自動暫存全部變更並提交?</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">暫存全部變更並提交</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.StageSelectedThenCommit" xml:space="preserve">僅暫存所選變更并提交</x:String>
|
||||
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">未包含任何檔案變更! 您是否仍要提交 (--allow-empty) 或者自動暫存變更並提交?</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Title" xml:space="preserve">系統提示</x:String>
|
||||
<x:String x:Key="Text.ConfirmRestart.Message" xml:space="preserve">您需要重新啟動此應用程式才能套用變更!</x:String>
|
||||
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">產生約定式提交訊息</x:String>
|
||||
@@ -523,6 +528,8 @@
|
||||
<x:String x:Key="Text.Hunk.Stage" xml:space="preserve">暫存</x:String>
|
||||
<x:String x:Key="Text.Hunk.Unstage" xml:space="preserve">取消暫存</x:String>
|
||||
<x:String x:Key="Text.Init" xml:space="preserve">初始化存放庫</x:String>
|
||||
<x:String x:Key="Text.Init.CommandTip" xml:space="preserve">在該路徑執行 git init 以初始化 git 倉庫?</x:String>
|
||||
<x:String x:Key="Text.Init.ErrorMessageTip" xml:space="preserve">無法在指定路徑開啟本機儲存庫。原因:</x:String>
|
||||
<x:String x:Key="Text.Init.Path" xml:space="preserve">路徑:</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">揀選 (cherry-pick) 操作進行中。</x:String>
|
||||
<x:String x:Key="Text.InProgress.CherryPick.Head" xml:space="preserve">正在處理提交</x:String>
|
||||
@@ -646,6 +653,7 @@
|
||||
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">在提交詳細資訊中顯示後續提交</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">在路線圖中顯示標籤</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">提交標題字數偵測</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.Use24Hours" xml:space="preserve">24小時制</x:String>
|
||||
<x:String x:Key="Text.Preferences.General.UseGitHubStyleAvatar" xml:space="preserve">產生 GitHub 風格的預設頭貼</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">Git 設定</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">自動換行轉換</x:String>
|
||||
@@ -973,9 +981,12 @@
|
||||
<x:String x:Key="Text.Workspace" xml:space="preserve">工作區: </x:String>
|
||||
<x:String x:Key="Text.Workspace.Configure" xml:space="preserve">設定工作區...</x:String>
|
||||
<x:String x:Key="Text.Worktree" xml:space="preserve">本機工作區</x:String>
|
||||
<x:String x:Key="Text.Worktree.Branch" xml:space="preserve">关联分支</x:String>
|
||||
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">複製工作區路徑</x:String>
|
||||
<x:String x:Key="Text.Worktree.Head" 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.Path" 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>
|
||||
<x:String x:Key="Text.Yes" xml:space="preserve">是</x:String>
|
||||
|
||||
@@ -182,6 +182,14 @@
|
||||
<Setter Property="FontSize" Value="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize}"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="AdornerLayer">
|
||||
<Setter Property="DefaultFocusAdorner">
|
||||
<FocusAdornerTemplate>
|
||||
<Rectangle Margin="0" Stroke="{DynamicResource Brush.FG1}" StrokeDashArray="1,2" StrokeThickness="1"/>
|
||||
</FocusAdornerTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ToolTip">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Popup}"/>
|
||||
@@ -190,9 +198,8 @@
|
||||
<Setter Property="TextBlock.TextDecorations" Value=""/>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid Effect="drop-shadow(0 0 8 #30000000)">
|
||||
<Border Margin="8"
|
||||
Padding="8,6"
|
||||
<Grid Margin="8" Effect="drop-shadow(0 0 8 #30000000)">
|
||||
<Border Padding="8,6"
|
||||
CornerRadius="4"
|
||||
Background="{DynamicResource Brush.Popup}"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
@@ -219,17 +226,10 @@
|
||||
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<Border Background="{DynamicResource Brush.Popup}" BorderThickness="0" Margin="4" CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect OffsetX="0" OffsetY="0" BlurRadius="4" Color="Black" Opacity=".6"/>
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
|
||||
<Grid Margin="4" Effect="drop-shadow(0 0 4 #A0000000)">
|
||||
<Border Name="LayoutRoot"
|
||||
Margin="4"
|
||||
Padding="12"
|
||||
Background="Transparent"
|
||||
Background="{DynamicResource Brush.Popup}"
|
||||
BorderThickness="0"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||
@@ -524,6 +524,9 @@
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
|
||||
<Setter Property="Opacity" Value=".56"/>
|
||||
</Style>
|
||||
<Style Selector="TextBlock.dropped">
|
||||
<Setter Property="TextDecorations" Value="Strikethrough"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="Run.issue_link">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Brush.Link}"/>
|
||||
@@ -813,15 +816,11 @@
|
||||
<Setter Property="VerticalOffset" Value="-4"/>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<Border Background="{DynamicResource Brush.Popup}" BorderThickness="0" Margin="4" CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect OffsetX="0" OffsetY="0" BlurRadius="4" Color="Black" Opacity=".6"/>
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
|
||||
<Grid Margin="4" Effect="drop-shadow(0 0 4 #A0000000)">
|
||||
<Border BorderThickness="0"
|
||||
Margin="8,4"
|
||||
Background="{DynamicResource Brush.Popup}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Padding="8,4"
|
||||
MaxWidth="{TemplateBinding MaxWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
|
||||
@@ -841,16 +840,9 @@
|
||||
<Style Selector="MenuFlyoutPresenter">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid>
|
||||
<Border Background="{DynamicResource Brush.Popup}" BorderThickness="0" Margin="4" CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect OffsetX="0" OffsetY="0" BlurRadius="4" Color="Black" Opacity=".6"/>
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
|
||||
<Grid Margin="4" Effect="drop-shadow(0 0 4 #A0000000)">
|
||||
<Border Name="LayoutRoot"
|
||||
Margin="4"
|
||||
Background="Transparent"
|
||||
Background="{DynamicResource Brush.Popup}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="0"
|
||||
Padding="4,2"
|
||||
@@ -961,14 +953,8 @@
|
||||
HorizontalOffset="-4"
|
||||
VerticalOffset="-4"
|
||||
IsOpen="{TemplateBinding IsSubMenuOpen, Mode=TwoWay}">
|
||||
<Grid>
|
||||
<Border Background="{DynamicResource Brush.Popup}" Margin="4" CornerRadius="{DynamicResource OverlayCornerRadius}">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect OffsetX="0" OffsetY="0" Color="Black" BlurRadius="4" Opacity=".6"/>
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
|
||||
<Border BorderThickness="0" Margin="8,4" MaxHeight="400">
|
||||
<Grid Margin="4" Effect="drop-shadow(0 0 4 #A0000000)">
|
||||
<Border BorderThickness="0" Padding="8,4" MaxHeight="400" Background="{DynamicResource Brush.Popup}" CornerRadius="{DynamicResource OverlayCornerRadius}">
|
||||
<ScrollViewer>
|
||||
<ItemsPresenter Name="PART_ItemsPresenter"
|
||||
Margin="{DynamicResource MenuFlyoutScrollerMargin}"
|
||||
@@ -1067,6 +1053,12 @@
|
||||
</Style>
|
||||
|
||||
<Style Selector="CheckBox">
|
||||
<Setter Property="FocusAdorner">
|
||||
<FocusAdornerTemplate>
|
||||
<Border/>
|
||||
</FocusAdornerTemplate>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
@@ -1085,16 +1077,32 @@
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^:pointerover /template/ Border#Border">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
<Style Selector="^:checked /template/ Path#Icon">
|
||||
<Setter Property="IsVisible" Value="True"/>
|
||||
</Style>
|
||||
<Style Selector="^:focus-visible /template/ Border#Border">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
|
||||
<Setter Property="BorderThickness" Value="2"/>
|
||||
</Style>
|
||||
<Style Selector="^:focus-visible:checked /template/ Border#Border">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
|
||||
<Setter Property="Background" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
<Style Selector="^:focus-visible:checked /template/ Path#Icon">
|
||||
<Setter Property="Fill" Value="White"/>
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="RadioButton">
|
||||
<Setter Property="FocusAdorner">
|
||||
<FocusAdornerTemplate>
|
||||
<Border/>
|
||||
</FocusAdornerTemplate>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid ColumnDefinitions="16,*" Background="Transparent">
|
||||
@@ -1136,9 +1144,26 @@
|
||||
<Style Selector="^:checked /template/ Ellipse#Dot">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
<Style Selector="^:focus-visible /template/ Ellipse#Border">
|
||||
<Setter Property="Stroke" Value="{DynamicResource Brush.Accent}"/>
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
<Style Selector="^:focus-visible /template/ Ellipse#Dot">
|
||||
<Setter Property="Stroke" Value="White"/>
|
||||
<Setter Property="Fill" Value="White"/>
|
||||
</Style>
|
||||
<Style Selector="^:focus-visible:checked /template/ Ellipse#Dot">
|
||||
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}"/>
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="RadioButton.switch_button">
|
||||
<Setter Property="FocusAdorner">
|
||||
<FocusAdornerTemplate>
|
||||
<Rectangle Margin="0" Stroke="{DynamicResource Brush.FG1}" StrokeDashArray="1,2" StrokeThickness="1"/>
|
||||
</FocusAdornerTemplate>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="Height" Value="24"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
|
||||
@@ -35,9 +35,8 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _selectedFile, value);
|
||||
}
|
||||
|
||||
public BlameCommandPalette(Launcher launcher, string repo)
|
||||
public BlameCommandPalette(string repo)
|
||||
{
|
||||
_launcher = launcher;
|
||||
_repo = repo;
|
||||
_isLoading = true;
|
||||
|
||||
@@ -61,17 +60,6 @@ namespace SourceGit.ViewModels
|
||||
});
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_launcher = null;
|
||||
_repo = null;
|
||||
_head = null;
|
||||
_repoFiles.Clear();
|
||||
_filter = null;
|
||||
_visibleFiles.Clear();
|
||||
_selectedFile = null;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
Filter = string.Empty;
|
||||
@@ -79,9 +67,12 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void Launch()
|
||||
{
|
||||
_repoFiles.Clear();
|
||||
_visibleFiles.Clear();
|
||||
Close();
|
||||
|
||||
if (!string.IsNullOrEmpty(_selectedFile))
|
||||
App.ShowWindow(new Blame(_repo, _selectedFile, _head));
|
||||
_launcher.CancelCommandPalette();
|
||||
}
|
||||
|
||||
private void UpdateVisible()
|
||||
@@ -117,7 +108,6 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private Launcher _launcher = null;
|
||||
private string _repo = null;
|
||||
private bool _isLoading = false;
|
||||
private Models.Commit _head = null;
|
||||
|
||||
@@ -28,22 +28,12 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public CheckoutCommandPalette(Launcher launcher, Repository repo)
|
||||
public CheckoutCommandPalette(Repository repo)
|
||||
{
|
||||
_launcher = launcher;
|
||||
_repo = repo;
|
||||
UpdateBranches();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_launcher = null;
|
||||
_repo = null;
|
||||
_branches.Clear();
|
||||
_selectedBranch = null;
|
||||
_filter = null;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
Filter = string.Empty;
|
||||
@@ -51,13 +41,11 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public async Task ExecAsync()
|
||||
{
|
||||
_launcher.CommandPalette = null;
|
||||
_branches.Clear();
|
||||
Close();
|
||||
|
||||
if (_selectedBranch != null)
|
||||
await _repo.CheckoutBranchAsync(_selectedBranch);
|
||||
|
||||
Dispose();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void UpdateBranches()
|
||||
@@ -94,7 +82,6 @@ namespace SourceGit.ViewModels
|
||||
SelectedBranch = autoSelected;
|
||||
}
|
||||
|
||||
private Launcher _launcher;
|
||||
private Repository _repo;
|
||||
private List<Models.Branch> _branches = [];
|
||||
private Models.Branch _selectedBranch = null;
|
||||
|
||||
@@ -32,24 +32,13 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public CompareCommandPalette(Launcher launcher, Repository repo, object basedOn)
|
||||
public CompareCommandPalette(Repository repo, object basedOn)
|
||||
{
|
||||
_launcher = launcher;
|
||||
_repo = repo;
|
||||
_basedOn = basedOn ?? repo.CurrentBranch;
|
||||
UpdateRefs();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_launcher = null;
|
||||
_repo = null;
|
||||
_basedOn = null;
|
||||
_compareTo = null;
|
||||
_refs.Clear();
|
||||
_filter = null;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
Filter = string.Empty;
|
||||
@@ -57,9 +46,11 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void Launch()
|
||||
{
|
||||
_refs.Clear();
|
||||
Close();
|
||||
|
||||
if (_compareTo != null)
|
||||
App.ShowWindow(new Compare(_repo, _basedOn, _compareTo));
|
||||
_launcher?.CancelCommandPalette();
|
||||
}
|
||||
|
||||
private void UpdateRefs()
|
||||
@@ -114,7 +105,6 @@ namespace SourceGit.ViewModels
|
||||
CompareTo = autoSelected;
|
||||
}
|
||||
|
||||
private Launcher _launcher;
|
||||
private Repository _repo;
|
||||
private object _basedOn = null;
|
||||
private object _compareTo = null;
|
||||
|
||||
114
src/ViewModels/ExecuteCustomActionCommandPalette.cs
Normal file
114
src/ViewModels/ExecuteCustomActionCommandPalette.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class ExecuteCustomActionCommandPaletteCmd
|
||||
{
|
||||
public Models.CustomAction Action { get; set; }
|
||||
public bool IsGlobal { get; set; }
|
||||
public string Name { get => Action.Name; }
|
||||
|
||||
public ExecuteCustomActionCommandPaletteCmd(Models.CustomAction action, bool isGlobal)
|
||||
{
|
||||
Action = action;
|
||||
IsGlobal = isGlobal;
|
||||
}
|
||||
}
|
||||
|
||||
public class ExecuteCustomActionCommandPalette : ICommandPalette
|
||||
{
|
||||
public List<ExecuteCustomActionCommandPaletteCmd> VisibleActions
|
||||
{
|
||||
get => _visibleActions;
|
||||
private set => SetProperty(ref _visibleActions, value);
|
||||
}
|
||||
|
||||
public ExecuteCustomActionCommandPaletteCmd Selected
|
||||
{
|
||||
get => _selected;
|
||||
set => SetProperty(ref _selected, value);
|
||||
}
|
||||
|
||||
public string Filter
|
||||
{
|
||||
get => _filter;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _filter, value))
|
||||
UpdateVisibleActions();
|
||||
}
|
||||
}
|
||||
|
||||
public ExecuteCustomActionCommandPalette(Repository repo)
|
||||
{
|
||||
_repo = repo;
|
||||
|
||||
var actions = repo.GetCustomActions(Models.CustomActionScope.Repository);
|
||||
foreach (var (action, menu) in actions)
|
||||
_actions.Add(new(action, menu.IsGlobal));
|
||||
|
||||
if (_actions.Count > 0)
|
||||
{
|
||||
_actions.Sort((l, r) =>
|
||||
{
|
||||
if (l.IsGlobal != r.IsGlobal)
|
||||
return l.IsGlobal ? -1 : 1;
|
||||
|
||||
return l.Name.CompareTo(r.Name, StringComparison.OrdinalIgnoreCase);
|
||||
});
|
||||
|
||||
_visibleActions = _actions;
|
||||
_selected = _actions[0];
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
Filter = string.Empty;
|
||||
}
|
||||
|
||||
public async Task ExecAsync()
|
||||
{
|
||||
_actions.Clear();
|
||||
_visibleActions.Clear();
|
||||
Close();
|
||||
|
||||
if (_selected != null)
|
||||
await _repo.ExecCustomActionAsync(_selected.Action, null);
|
||||
}
|
||||
|
||||
private void UpdateVisibleActions()
|
||||
{
|
||||
var filter = _filter?.Trim();
|
||||
if (string.IsNullOrEmpty(filter))
|
||||
{
|
||||
VisibleActions = _actions;
|
||||
return;
|
||||
}
|
||||
|
||||
var visible = new List<ExecuteCustomActionCommandPaletteCmd>();
|
||||
foreach (var act in _actions)
|
||||
{
|
||||
if (act.Name.Contains(filter, StringComparison.OrdinalIgnoreCase))
|
||||
visible.Add(act);
|
||||
}
|
||||
|
||||
var autoSelected = _selected;
|
||||
if (visible.Count == 0)
|
||||
autoSelected = null;
|
||||
else if (_selected == null || !visible.Contains(_selected))
|
||||
autoSelected = visible[0];
|
||||
|
||||
VisibleActions = visible;
|
||||
Selected = autoSelected;
|
||||
}
|
||||
|
||||
private Repository _repo;
|
||||
private List<ExecuteCustomActionCommandPaletteCmd> _actions = [];
|
||||
private List<ExecuteCustomActionCommandPaletteCmd> _visibleActions = [];
|
||||
private ExecuteCustomActionCommandPaletteCmd _selected = null;
|
||||
private string _filter;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Collections;
|
||||
@@ -36,10 +35,10 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _viewContent, value);
|
||||
}
|
||||
|
||||
public FileHistoriesSingleRevision(string repo, string file, Models.Commit revision, bool prevIsDiffMode)
|
||||
public FileHistoriesSingleRevision(string repo, Models.FileVersion revision, bool prevIsDiffMode)
|
||||
{
|
||||
_repo = repo;
|
||||
_file = file;
|
||||
_file = revision.Path;
|
||||
_revision = revision;
|
||||
_isDiffMode = prevIsDiffMode;
|
||||
_viewContent = null;
|
||||
@@ -75,7 +74,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (_isDiffMode)
|
||||
{
|
||||
SetViewContentAsDiff();
|
||||
ViewContent = new DiffContext(_repo, new(_revision), _viewContent as DiffContext);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -153,28 +152,22 @@ namespace SourceGit.ViewModels
|
||||
return new FileHistoriesRevisionFile(_file);
|
||||
}
|
||||
|
||||
private void SetViewContentAsDiff()
|
||||
{
|
||||
var option = new Models.DiffOption(_revision, _file);
|
||||
ViewContent = new DiffContext(_repo, option, _viewContent as DiffContext);
|
||||
}
|
||||
|
||||
private string _repo = null;
|
||||
private string _file = null;
|
||||
private Models.Commit _revision = null;
|
||||
private Models.FileVersion _revision = null;
|
||||
private bool _isDiffMode = false;
|
||||
private object _viewContent = null;
|
||||
}
|
||||
|
||||
public class FileHistoriesCompareRevisions : ObservableObject
|
||||
{
|
||||
public Models.Commit StartPoint
|
||||
public Models.FileVersion StartPoint
|
||||
{
|
||||
get => _startPoint;
|
||||
set => SetProperty(ref _startPoint, value);
|
||||
}
|
||||
|
||||
public Models.Commit EndPoint
|
||||
public Models.FileVersion EndPoint
|
||||
{
|
||||
get => _endPoint;
|
||||
set => SetProperty(ref _endPoint, value);
|
||||
@@ -186,19 +179,18 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _viewContent, value);
|
||||
}
|
||||
|
||||
public FileHistoriesCompareRevisions(string repo, string file, Models.Commit start, Models.Commit end)
|
||||
public FileHistoriesCompareRevisions(string repo, Models.FileVersion start, Models.FileVersion end)
|
||||
{
|
||||
_repo = repo;
|
||||
_file = file;
|
||||
_startPoint = start;
|
||||
_endPoint = end;
|
||||
RefreshViewContent();
|
||||
_viewContent = new(_repo, new(start, end));
|
||||
}
|
||||
|
||||
public void Swap()
|
||||
{
|
||||
(StartPoint, EndPoint) = (_endPoint, _startPoint);
|
||||
RefreshViewContent();
|
||||
ViewContent = new(_repo, new(_startPoint, _endPoint), _viewContent);
|
||||
}
|
||||
|
||||
public async Task<bool> SaveAsPatch(string saveTo)
|
||||
@@ -208,27 +200,9 @@ namespace SourceGit.ViewModels
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private void RefreshViewContent()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
_changes = await new Commands.CompareRevisions(_repo, _startPoint.SHA, _endPoint.SHA, _file).ReadAsync().ConfigureAwait(false);
|
||||
if (_changes.Count == 0)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => ViewContent = null);
|
||||
}
|
||||
else
|
||||
{
|
||||
var option = new Models.DiffOption(_startPoint.SHA, _endPoint.SHA, _changes[0]);
|
||||
Dispatcher.UIThread.Post(() => ViewContent = new DiffContext(_repo, option, _viewContent));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private string _repo = null;
|
||||
private string _file = null;
|
||||
private Models.Commit _startPoint = null;
|
||||
private Models.Commit _endPoint = null;
|
||||
private Models.FileVersion _startPoint = null;
|
||||
private Models.FileVersion _endPoint = null;
|
||||
private List<Models.Change> _changes = [];
|
||||
private DiffContext _viewContent = null;
|
||||
}
|
||||
@@ -246,13 +220,13 @@ namespace SourceGit.ViewModels
|
||||
private set => SetProperty(ref _isLoading, value);
|
||||
}
|
||||
|
||||
public List<Models.Commit> Commits
|
||||
public List<Models.FileVersion> Revisions
|
||||
{
|
||||
get => _commits;
|
||||
set => SetProperty(ref _commits, value);
|
||||
get => _revisions;
|
||||
set => SetProperty(ref _revisions, value);
|
||||
}
|
||||
|
||||
public AvaloniaList<Models.Commit> SelectedCommits
|
||||
public AvaloniaList<Models.FileVersion> SelectedRevisions
|
||||
{
|
||||
get;
|
||||
set;
|
||||
@@ -275,41 +249,34 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var argsBuilder = new StringBuilder();
|
||||
argsBuilder
|
||||
.Append("--date-order -n 10000 ")
|
||||
.Append(commit ?? string.Empty)
|
||||
.Append(" -- ")
|
||||
.Append(file.Quoted());
|
||||
|
||||
var commits = await new Commands.QueryCommits(_repo, argsBuilder.ToString(), false)
|
||||
var revisions = await new Commands.QueryFileHistory(_repo, file, commit)
|
||||
.GetResultAsync()
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IsLoading = false;
|
||||
Commits = commits;
|
||||
if (Commits.Count > 0)
|
||||
SelectedCommits.Add(Commits[0]);
|
||||
Revisions = revisions;
|
||||
if (revisions.Count > 0)
|
||||
SelectedRevisions.Add(revisions[0]);
|
||||
});
|
||||
});
|
||||
|
||||
SelectedCommits.CollectionChanged += (_, _) =>
|
||||
SelectedRevisions.CollectionChanged += (_, _) =>
|
||||
{
|
||||
if (_viewContent is FileHistoriesSingleRevision singleRevision)
|
||||
_prevIsDiffMode = singleRevision.IsDiffMode;
|
||||
|
||||
ViewContent = SelectedCommits.Count switch
|
||||
ViewContent = SelectedRevisions.Count switch
|
||||
{
|
||||
1 => new FileHistoriesSingleRevision(_repo, file, SelectedCommits[0], _prevIsDiffMode),
|
||||
2 => new FileHistoriesCompareRevisions(_repo, file, SelectedCommits[0], SelectedCommits[1]),
|
||||
_ => SelectedCommits.Count,
|
||||
1 => new FileHistoriesSingleRevision(_repo, SelectedRevisions[0], _prevIsDiffMode),
|
||||
2 => new FileHistoriesCompareRevisions(_repo, SelectedRevisions[0], SelectedRevisions[1]),
|
||||
_ => SelectedRevisions.Count,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
public void NavigateToCommit(Models.Commit commit)
|
||||
public void NavigateToCommit(Models.FileVersion revision)
|
||||
{
|
||||
var launcher = App.GetLauncher();
|
||||
if (launcher != null)
|
||||
@@ -318,16 +285,16 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (page.Data is Repository repo && repo.FullPath.Equals(_repo, StringComparison.Ordinal))
|
||||
{
|
||||
repo.NavigateToCommit(commit.SHA);
|
||||
repo.NavigateToCommit(revision.SHA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetCommitFullMessage(Models.Commit commit)
|
||||
public string GetCommitFullMessage(Models.FileVersion revision)
|
||||
{
|
||||
var sha = commit.SHA;
|
||||
var sha = revision.SHA;
|
||||
if (_fullCommitMessages.TryGetValue(sha, out var msg))
|
||||
return msg;
|
||||
|
||||
@@ -339,7 +306,7 @@ namespace SourceGit.ViewModels
|
||||
private readonly string _repo = null;
|
||||
private bool _isLoading = true;
|
||||
private bool _prevIsDiffMode = true;
|
||||
private List<Models.Commit> _commits = null;
|
||||
private List<Models.FileVersion> _revisions = null;
|
||||
private Dictionary<string, string> _fullCommitMessages = new();
|
||||
private object _viewContent = null;
|
||||
}
|
||||
|
||||
@@ -35,9 +35,8 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _selectedFile, value);
|
||||
}
|
||||
|
||||
public FileHistoryCommandPalette(Launcher launcher, string repo)
|
||||
public FileHistoryCommandPalette(string repo)
|
||||
{
|
||||
_launcher = launcher;
|
||||
_repo = repo;
|
||||
_isLoading = true;
|
||||
|
||||
@@ -56,16 +55,6 @@ namespace SourceGit.ViewModels
|
||||
});
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_launcher = null;
|
||||
_repo = null;
|
||||
_repoFiles.Clear();
|
||||
_filter = null;
|
||||
_visibleFiles.Clear();
|
||||
_selectedFile = null;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
Filter = string.Empty;
|
||||
@@ -73,9 +62,12 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void Launch()
|
||||
{
|
||||
_repoFiles.Clear();
|
||||
_visibleFiles.Clear();
|
||||
Close();
|
||||
|
||||
if (!string.IsNullOrEmpty(_selectedFile))
|
||||
App.ShowWindow(new FileHistories(_repo, _selectedFile));
|
||||
_launcher.CancelCommandPalette();
|
||||
}
|
||||
|
||||
private void UpdateVisible()
|
||||
@@ -111,7 +103,6 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private Launcher _launcher = null;
|
||||
private string _repo = null;
|
||||
private bool _isLoading = false;
|
||||
private List<string> _repoFiles = null;
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class ICommandPalette : ObservableObject, IDisposable
|
||||
public class ICommandPalette : ObservableObject
|
||||
{
|
||||
public void Dispose()
|
||||
public void Open()
|
||||
{
|
||||
Cleanup();
|
||||
var host = App.GetLauncher();
|
||||
if (host != null)
|
||||
host.CommandPalette = this;
|
||||
}
|
||||
|
||||
public virtual void Cleanup()
|
||||
public void Close()
|
||||
{
|
||||
var host = App.GetLauncher();
|
||||
if (host != null)
|
||||
host.CommandPalette = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@ namespace SourceGit.ViewModels
|
||||
_pageId = pageId;
|
||||
_targetPath = path;
|
||||
_parentNode = parent;
|
||||
Reason = string.IsNullOrEmpty(reason) ? "Invalid repository detected!" : reason;
|
||||
|
||||
Reason = string.IsNullOrEmpty(reason) ? "unknown error" : reason;
|
||||
Reason = Reason.Trim();
|
||||
}
|
||||
|
||||
public override async Task<bool> Sure()
|
||||
|
||||
@@ -76,12 +76,6 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _showEditMessageButton, value);
|
||||
}
|
||||
|
||||
public bool IsFullMessageUsed
|
||||
{
|
||||
get => _isFullMessageUsed;
|
||||
set => SetProperty(ref _isFullMessageUsed, value);
|
||||
}
|
||||
|
||||
public Thickness DropDirectionIndicator
|
||||
{
|
||||
get => _dropDirectionIndicator;
|
||||
@@ -108,7 +102,6 @@ namespace SourceGit.ViewModels
|
||||
private string _fullMessage;
|
||||
private bool _canSquashOrFixup = true;
|
||||
private bool _showEditMessageButton = false;
|
||||
private bool _isFullMessageUsed = true;
|
||||
private Thickness _dropDirectionIndicator = new Thickness(0);
|
||||
}
|
||||
|
||||
@@ -354,7 +347,6 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (item.Action == Models.InteractiveRebaseAction.Drop)
|
||||
{
|
||||
item.IsFullMessageUsed = false;
|
||||
item.ShowEditMessageButton = false;
|
||||
item.PendingType = hasPending ? Models.InteractiveRebasePendingType.Ignore : Models.InteractiveRebasePendingType.None;
|
||||
item.FullMessage = item.OriginalFullMessage;
|
||||
@@ -365,7 +357,6 @@ namespace SourceGit.ViewModels
|
||||
if (item.Action == Models.InteractiveRebaseAction.Fixup ||
|
||||
item.Action == Models.InteractiveRebaseAction.Squash)
|
||||
{
|
||||
item.IsFullMessageUsed = false;
|
||||
item.ShowEditMessageButton = false;
|
||||
item.PendingType = hasPending ? Models.InteractiveRebasePendingType.Pending : Models.InteractiveRebasePendingType.Last;
|
||||
item.FullMessage = item.OriginalFullMessage;
|
||||
@@ -382,7 +373,6 @@ namespace SourceGit.ViewModels
|
||||
item.Action == Models.InteractiveRebaseAction.Edit)
|
||||
{
|
||||
var oldPendingType = item.PendingType;
|
||||
item.IsFullMessageUsed = true;
|
||||
item.ShowEditMessageButton = true;
|
||||
item.PendingType = hasPending ? Models.InteractiveRebasePendingType.Target : Models.InteractiveRebasePendingType.None;
|
||||
|
||||
@@ -412,7 +402,6 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (item.Action == Models.InteractiveRebaseAction.Pick)
|
||||
{
|
||||
item.IsFullMessageUsed = true;
|
||||
item.IsMessageUserEdited = false;
|
||||
|
||||
if (hasPending)
|
||||
|
||||
@@ -347,23 +347,6 @@ namespace SourceGit.ViewModels
|
||||
ActivePage = page;
|
||||
}
|
||||
|
||||
public void OpenCommandPalette(ICommandPalette commandPalette)
|
||||
{
|
||||
var old = _commandPalette;
|
||||
CommandPalette = commandPalette;
|
||||
old?.Dispose();
|
||||
}
|
||||
|
||||
public void CancelCommandPalette()
|
||||
{
|
||||
if (_commandPalette != null)
|
||||
{
|
||||
_commandPalette?.Dispose();
|
||||
CommandPalette = null;
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
public void DispatchNotification(string pageId, string message, bool isError)
|
||||
{
|
||||
if (!Dispatcher.UIThread.CheckAccess())
|
||||
@@ -453,7 +436,7 @@ namespace SourceGit.ViewModels
|
||||
builder.Append(" - ").Append(_activeWorkspace.Name);
|
||||
|
||||
Title = builder.ToString();
|
||||
CancelCommandPalette();
|
||||
CommandPalette = null;
|
||||
}
|
||||
|
||||
private Workspace _activeWorkspace;
|
||||
|
||||
@@ -60,17 +60,6 @@ namespace SourceGit.ViewModels
|
||||
UpdateVisible();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_launcher = null;
|
||||
_opened.Clear();
|
||||
_visiblePages.Clear();
|
||||
_visibleRepos.Clear();
|
||||
_searchFilter = null;
|
||||
_selectedPage = null;
|
||||
_selectedRepo = null;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
SearchFilter = string.Empty;
|
||||
@@ -78,12 +67,15 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void OpenOrSwitchTo()
|
||||
{
|
||||
_opened.Clear();
|
||||
_visiblePages.Clear();
|
||||
_visibleRepos.Clear();
|
||||
Close();
|
||||
|
||||
if (_selectedPage != null)
|
||||
_launcher.ActivePage = _selectedPage;
|
||||
else if (_selectedRepo != null)
|
||||
_launcher.OpenRepositoryInTab(_selectedRepo, null);
|
||||
|
||||
_launcher?.CancelCommandPalette();
|
||||
}
|
||||
|
||||
private void UpdateVisible()
|
||||
|
||||
@@ -27,22 +27,12 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _selectedBranch, value);
|
||||
}
|
||||
|
||||
public MergeCommandPalette(Launcher launcher, Repository repo)
|
||||
public MergeCommandPalette(Repository repo)
|
||||
{
|
||||
_launcher = launcher;
|
||||
_repo = repo;
|
||||
UpdateBranches();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_launcher = null;
|
||||
_repo = null;
|
||||
_branches.Clear();
|
||||
_filter = null;
|
||||
_selectedBranch = null;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
Filter = string.Empty;
|
||||
@@ -50,10 +40,11 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void Launch()
|
||||
{
|
||||
_branches.Clear();
|
||||
Close();
|
||||
|
||||
if (_repo.CanCreatePopup() && _selectedBranch != null)
|
||||
_repo.ShowPopup(new Merge(_repo, _selectedBranch, _repo.CurrentBranch.Name, false));
|
||||
|
||||
_launcher?.CancelCommandPalette();
|
||||
}
|
||||
|
||||
private void UpdateBranches()
|
||||
@@ -90,7 +81,6 @@ namespace SourceGit.ViewModels
|
||||
SelectedBranch = autoSelected;
|
||||
}
|
||||
|
||||
private Launcher _launcher = null;
|
||||
private Repository _repo = null;
|
||||
private List<Models.Branch> _branches = new List<Models.Branch>();
|
||||
private string _filter = string.Empty;
|
||||
|
||||
@@ -35,9 +35,8 @@ namespace SourceGit.ViewModels
|
||||
set => SetProperty(ref _selectedFile, value);
|
||||
}
|
||||
|
||||
public OpenFileCommandPalette(Launcher launcher, string repo)
|
||||
public OpenFileCommandPalette(string repo)
|
||||
{
|
||||
_launcher = launcher;
|
||||
_repo = repo;
|
||||
_isLoading = true;
|
||||
|
||||
@@ -56,16 +55,6 @@ namespace SourceGit.ViewModels
|
||||
});
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_launcher = null;
|
||||
_repo = null;
|
||||
_repoFiles.Clear();
|
||||
_filter = null;
|
||||
_visibleFiles.Clear();
|
||||
_selectedFile = null;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
Filter = string.Empty;
|
||||
@@ -73,10 +62,12 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void Launch()
|
||||
{
|
||||
_repoFiles.Clear();
|
||||
_visibleFiles.Clear();
|
||||
Close();
|
||||
|
||||
if (!string.IsNullOrEmpty(_selectedFile))
|
||||
Native.OS.OpenWithDefaultEditor(Native.OS.GetAbsPath(_repo, _selectedFile));
|
||||
|
||||
_launcher.CancelCommandPalette();
|
||||
}
|
||||
|
||||
private void UpdateVisible()
|
||||
@@ -112,7 +103,6 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private Launcher _launcher = null;
|
||||
private string _repo = null;
|
||||
private bool _isLoading = false;
|
||||
private List<string> _repoFiles = null;
|
||||
|
||||
@@ -155,6 +155,19 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool Use24Hours
|
||||
{
|
||||
get => Models.DateTimeFormat.Use24Hours;
|
||||
set
|
||||
{
|
||||
if (value != Models.DateTimeFormat.Use24Hours)
|
||||
{
|
||||
Models.DateTimeFormat.Use24Hours = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseFixedTabWidth
|
||||
{
|
||||
get => _useFixedTabWidth;
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
public class RemoveWorktree : Popup
|
||||
{
|
||||
public Models.Worktree Target
|
||||
public Worktree Target
|
||||
{
|
||||
get;
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace SourceGit.ViewModels
|
||||
set;
|
||||
} = false;
|
||||
|
||||
public RemoveWorktree(Repository repo, Models.Worktree target)
|
||||
public RemoveWorktree(Repository repo, Worktree target)
|
||||
{
|
||||
_repo = repo;
|
||||
Target = target;
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace SourceGit.ViewModels
|
||||
private set => SetProperty(ref _remoteBranchTrees, value);
|
||||
}
|
||||
|
||||
public List<Models.Worktree> Worktrees
|
||||
public List<Worktree> Worktrees
|
||||
{
|
||||
get => _worktrees;
|
||||
private set => SetProperty(ref _worktrees, value);
|
||||
@@ -1076,22 +1076,7 @@ namespace SourceGit.ViewModels
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var worktrees = await new Commands.Worktree(FullPath).ReadAllAsync().ConfigureAwait(false);
|
||||
if (worktrees.Count == 0)
|
||||
{
|
||||
Dispatcher.UIThread.Invoke(() => Worktrees = worktrees);
|
||||
return;
|
||||
}
|
||||
|
||||
var cleaned = new List<Models.Worktree>();
|
||||
foreach (var worktree in worktrees)
|
||||
{
|
||||
if (worktree.FullPath.Equals(FullPath, StringComparison.Ordinal) ||
|
||||
worktree.FullPath.Equals(GitDir, StringComparison.Ordinal))
|
||||
continue;
|
||||
|
||||
cleaned.Add(worktree);
|
||||
}
|
||||
|
||||
var cleaned = Worktree.Build(FullPath, worktrees);
|
||||
Dispatcher.UIThread.Invoke(() => Worktrees = cleaned);
|
||||
});
|
||||
}
|
||||
@@ -1303,7 +1288,7 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if (branch.IsLocal)
|
||||
{
|
||||
var worktree = _worktrees.Find(x => x.Branch.Equals(branch.FullName, StringComparison.Ordinal));
|
||||
var worktree = _worktrees.Find(x => x.IsAttachedTo(branch));
|
||||
if (worktree != null)
|
||||
{
|
||||
OpenWorktree(worktree);
|
||||
@@ -1470,8 +1455,11 @@ namespace SourceGit.ViewModels
|
||||
await ShowAndStartPopupAsync(new PruneWorktrees(this));
|
||||
}
|
||||
|
||||
public void OpenWorktree(Models.Worktree worktree)
|
||||
public void OpenWorktree(Worktree worktree)
|
||||
{
|
||||
if (worktree.IsCurrent)
|
||||
return;
|
||||
|
||||
var node = Preferences.Instance.FindNode(worktree.FullPath) ??
|
||||
new RepositoryNode
|
||||
{
|
||||
@@ -1484,7 +1472,7 @@ namespace SourceGit.ViewModels
|
||||
App.GetLauncher().OpenRepositoryInTab(node, null);
|
||||
}
|
||||
|
||||
public async Task LockWorktreeAsync(Models.Worktree worktree)
|
||||
public async Task LockWorktreeAsync(Worktree worktree)
|
||||
{
|
||||
using var lockWatcher = _watcher?.Lock();
|
||||
var log = CreateLog("Lock Worktree");
|
||||
@@ -1494,7 +1482,7 @@ namespace SourceGit.ViewModels
|
||||
log.Complete();
|
||||
}
|
||||
|
||||
public async Task UnlockWorktreeAsync(Models.Worktree worktree)
|
||||
public async Task UnlockWorktreeAsync(Worktree worktree)
|
||||
{
|
||||
using var lockWatcher = _watcher?.Lock();
|
||||
var log = CreateLog("Unlock Worktree");
|
||||
@@ -1864,7 +1852,7 @@ namespace SourceGit.ViewModels
|
||||
private Models.Branch _currentBranch = null;
|
||||
private List<BranchTreeNode> _localBranchTrees = [];
|
||||
private List<BranchTreeNode> _remoteBranchTrees = [];
|
||||
private List<Models.Worktree> _worktrees = [];
|
||||
private List<Worktree> _worktrees = [];
|
||||
private List<Models.Tag> _tags = [];
|
||||
private object _visibleTags = null;
|
||||
private List<Models.Submodule> _submodules = [];
|
||||
|
||||
@@ -5,15 +5,29 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
public class RepositoryCommandPaletteCmd
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string Keyword { get; set; }
|
||||
public string Icon { get; set; }
|
||||
public bool CloseBeforeExec { get; set; }
|
||||
public Action Action { get; set; }
|
||||
public string Label => $"{App.Text(Key)}...";
|
||||
|
||||
public RepositoryCommandPaletteCmd(string key, Action action)
|
||||
public RepositoryCommandPaletteCmd(string labelKey, string keyword, string icon, Action action)
|
||||
{
|
||||
Key = key;
|
||||
Label = $"{App.Text(labelKey)}...";
|
||||
Keyword = keyword;
|
||||
Icon = icon;
|
||||
CloseBeforeExec = true;
|
||||
Action = action;
|
||||
}
|
||||
|
||||
public RepositoryCommandPaletteCmd(string labelKey, string keyword, string icon, ICommandPalette child)
|
||||
{
|
||||
Label = $"{App.Text(labelKey)}...";
|
||||
Keyword = keyword;
|
||||
Icon = icon;
|
||||
CloseBeforeExec = false;
|
||||
Action = () => child.Open();
|
||||
}
|
||||
}
|
||||
|
||||
public class RepositoryCommandPalette : ICommandPalette
|
||||
@@ -40,61 +54,32 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public RepositoryCommandPalette(Launcher launcher, Repository repo)
|
||||
public RepositoryCommandPalette(Repository repo)
|
||||
{
|
||||
_launcher = launcher;
|
||||
_repo = repo;
|
||||
// Sub-CommandPalettes
|
||||
_cmds.Add(new("Blame", "blame", "Blame", new BlameCommandPalette(repo.FullPath)));
|
||||
_cmds.Add(new("Checkout", "checkout", "Check", new CheckoutCommandPalette(repo)));
|
||||
_cmds.Add(new("Compare.WithHead", "compare", "Compare", new CompareCommandPalette(repo, null)));
|
||||
_cmds.Add(new("FileHistory", "history", "Histories", new FileHistoryCommandPalette(repo.FullPath)));
|
||||
_cmds.Add(new("Merge", "merge", "Merge", new MergeCommandPalette(repo)));
|
||||
_cmds.Add(new("OpenFile", "open", "OpenWith", new OpenFileCommandPalette(repo.FullPath)));
|
||||
_cmds.Add(new("Repository.CustomActions", "custom actions", "Action", new ExecuteCustomActionCommandPalette(repo)));
|
||||
|
||||
_cmds.Add(new("Blame", () =>
|
||||
{
|
||||
var sub = new BlameCommandPalette(_launcher, _repo.FullPath);
|
||||
_launcher.OpenCommandPalette(sub);
|
||||
}));
|
||||
|
||||
_cmds.Add(new("Checkout", () =>
|
||||
{
|
||||
var sub = new CheckoutCommandPalette(_launcher, _repo);
|
||||
_launcher.OpenCommandPalette(sub);
|
||||
}));
|
||||
|
||||
_cmds.Add(new("Compare.WithHead", () =>
|
||||
{
|
||||
var sub = new CompareCommandPalette(_launcher, _repo, _repo.CurrentBranch);
|
||||
_launcher.OpenCommandPalette(sub);
|
||||
}));
|
||||
|
||||
_cmds.Add(new("FileHistory", () =>
|
||||
{
|
||||
var sub = new FileHistoryCommandPalette(_launcher, _repo.FullPath);
|
||||
_launcher.OpenCommandPalette(sub);
|
||||
}));
|
||||
|
||||
_cmds.Add(new("Merge", () =>
|
||||
{
|
||||
var sub = new MergeCommandPalette(_launcher, _repo);
|
||||
_launcher.OpenCommandPalette(sub);
|
||||
}));
|
||||
|
||||
_cmds.Add(new("OpenFile", () =>
|
||||
{
|
||||
var sub = new OpenFileCommandPalette(_launcher, _repo.FullPath);
|
||||
_launcher.OpenCommandPalette(sub);
|
||||
}));
|
||||
// Raw-Actions
|
||||
_cmds.Add(new("Repository.NewBranch", "create branch", "Branch.Add", () => repo.CreateNewBranch()));
|
||||
_cmds.Add(new("CreateTag.Title", "create tag", "Tag.Add", () => repo.CreateNewTag()));
|
||||
_cmds.Add(new("Fetch", "fetch", "Fetch", async () => await repo.FetchAsync(false)));
|
||||
_cmds.Add(new("Pull.Title", "pull", "Pull", async () => await repo.PullAsync(false)));
|
||||
_cmds.Add(new("Push", "push", "Push", async () => await repo.PushAsync(false)));
|
||||
_cmds.Add(new("Stash.Title", "stash", "Stashes.Add", async () => await repo.StashAllAsync(false)));
|
||||
_cmds.Add(new("Apply.Title", "apply", "Diff", () => repo.ApplyPatch()));
|
||||
_cmds.Add(new("Configure", "configure", "Settings", async () => await App.ShowDialog(new RepositoryConfigure(repo))));
|
||||
|
||||
_cmds.Sort((l, r) => l.Label.CompareTo(r.Label));
|
||||
_visibleCmds = _cmds;
|
||||
_selectedCmd = _cmds[0];
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
_launcher = null;
|
||||
_repo = null;
|
||||
_cmds.Clear();
|
||||
_visibleCmds.Clear();
|
||||
_selectedCmd = null;
|
||||
_filter = null;
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
Filter = string.Empty;
|
||||
@@ -102,10 +87,16 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void Exec()
|
||||
{
|
||||
_cmds.Clear();
|
||||
_visibleCmds.Clear();
|
||||
|
||||
if (_selectedCmd != null)
|
||||
{
|
||||
if (_selectedCmd.CloseBeforeExec)
|
||||
Close();
|
||||
|
||||
_selectedCmd.Action?.Invoke();
|
||||
else
|
||||
_launcher?.CancelCommandPalette();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVisible()
|
||||
@@ -120,8 +111,8 @@ namespace SourceGit.ViewModels
|
||||
|
||||
foreach (var cmd in _cmds)
|
||||
{
|
||||
if (cmd.Key.Contains(_filter, StringComparison.OrdinalIgnoreCase) ||
|
||||
cmd.Label.Contains(_filter, StringComparison.OrdinalIgnoreCase))
|
||||
if (cmd.Label.Contains(_filter, StringComparison.OrdinalIgnoreCase) ||
|
||||
cmd.Keyword.Contains(_filter, StringComparison.OrdinalIgnoreCase))
|
||||
visible.Add(cmd);
|
||||
}
|
||||
|
||||
@@ -134,8 +125,6 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private Launcher _launcher = null;
|
||||
private Repository _repo = null;
|
||||
private List<RepositoryCommandPaletteCmd> _cmds = [];
|
||||
private List<RepositoryCommandPaletteCmd> _visibleCmds = [];
|
||||
private RepositoryCommandPaletteCmd _selectedCmd = null;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace SourceGit.ViewModels
|
||||
public string Name { get; private set; }
|
||||
public bool IsAnnotated { get; private set; }
|
||||
public Models.User Creator { get; private set; }
|
||||
public string CreatorDateStr { get; private set; }
|
||||
public ulong CreatorDate { get; private set; }
|
||||
public string Message { get; private set; }
|
||||
|
||||
public TagToolTip(Models.Tag t)
|
||||
@@ -21,7 +21,7 @@ namespace SourceGit.ViewModels
|
||||
Name = t.Name;
|
||||
IsAnnotated = t.IsAnnotated;
|
||||
Creator = t.Creator;
|
||||
CreatorDateStr = t.CreatorDateStr;
|
||||
CreatorDate = t.CreatorDate;
|
||||
Message = t.Message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -643,12 +643,14 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
if ((!autoStage && _staged.Count == 0) || (autoStage && _cached.Count == 0))
|
||||
{
|
||||
var rs = await App.AskConfirmEmptyCommitAsync(_cached.Count > 0);
|
||||
var rs = await App.AskConfirmEmptyCommitAsync(_cached.Count > 0, _selectedUnstaged is { Count: > 0 });
|
||||
if (rs == Models.ConfirmEmptyCommitResult.Cancel)
|
||||
return;
|
||||
|
||||
if (rs == Models.ConfirmEmptyCommitResult.StageAllAndCommit)
|
||||
autoStage = true;
|
||||
else if (rs == Models.ConfirmEmptyCommitResult.StageSelectedAndCommit)
|
||||
await StageChangesAsync(_selectedUnstaged, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
112
src/ViewModels/Worktree.cs
Normal file
112
src/ViewModels/Worktree.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class Worktree : ObservableObject
|
||||
{
|
||||
public Models.Worktree Backend { get; private set; }
|
||||
public bool IsMain { get; private set; }
|
||||
public bool IsCurrent { get; private set; }
|
||||
public bool IsLast { get; private set; }
|
||||
public string DisplayPath { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
public string Branch { get; private set; }
|
||||
|
||||
public bool IsLocked
|
||||
{
|
||||
get => _isLocked;
|
||||
set => SetProperty(ref _isLocked, value);
|
||||
}
|
||||
|
||||
public string FullPath => Backend.FullPath;
|
||||
public string Head => Backend.Head;
|
||||
|
||||
public Worktree(DirectoryInfo repo, Models.Worktree wt, bool isMain, bool isLast)
|
||||
{
|
||||
Backend = wt;
|
||||
IsMain = isMain;
|
||||
IsCurrent = IsCurrentWorktree(repo, wt);
|
||||
IsLast = isLast;
|
||||
DisplayPath = IsCurrent ? string.Empty : Path.GetRelativePath(repo.FullName, wt.FullPath);
|
||||
Name = GenerateName();
|
||||
Branch = GenerateBranchName();
|
||||
IsLocked = wt.IsLocked;
|
||||
}
|
||||
|
||||
public static List<Worktree> Build(string repo, List<Models.Worktree> worktrees)
|
||||
{
|
||||
if (worktrees is not { Count: > 1 })
|
||||
return [];
|
||||
|
||||
var repoDir = new DirectoryInfo(repo);
|
||||
var nodes = new List<Worktree>();
|
||||
nodes.Add(new(repoDir, worktrees[0], true, false));
|
||||
for (int i = 1; i < worktrees.Count; i++)
|
||||
nodes.Add(new(repoDir, worktrees[i], false, i == worktrees.Count - 1));
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public bool IsAttachedTo(Models.Branch branch)
|
||||
{
|
||||
if (string.IsNullOrEmpty(branch.WorktreePath))
|
||||
return false;
|
||||
|
||||
var wtDir = new DirectoryInfo(Backend.FullPath);
|
||||
var test = new DirectoryInfo(branch.WorktreePath);
|
||||
return test.FullName.Equals(wtDir.FullName, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private bool IsCurrentWorktree(DirectoryInfo repo, Models.Worktree wt)
|
||||
{
|
||||
var wtDir = new DirectoryInfo(wt.FullPath);
|
||||
return wtDir.FullName.Equals(repo.FullName, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private string GenerateName()
|
||||
{
|
||||
if (IsMain)
|
||||
return Path.GetFileName(Backend.FullPath);
|
||||
|
||||
if (Backend.IsDetached)
|
||||
return $"detached HEAD at {Backend.Head.AsSpan(10)}";
|
||||
|
||||
var b = Backend.Branch;
|
||||
|
||||
if (b.StartsWith("refs/heads/", StringComparison.Ordinal))
|
||||
return b.Substring(11);
|
||||
|
||||
if (b.StartsWith("refs/remotes/", StringComparison.Ordinal))
|
||||
return b.Substring(13);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
private string GenerateBranchName()
|
||||
{
|
||||
if (Backend.IsBare)
|
||||
return "-- (default)";
|
||||
|
||||
if (Backend.IsDetached)
|
||||
return "-- (detached)";
|
||||
|
||||
if (string.IsNullOrEmpty(Backend.Branch))
|
||||
return "-- (unknown)";
|
||||
|
||||
var b = Backend.Branch;
|
||||
|
||||
if (b.StartsWith("refs/heads/", StringComparison.Ordinal))
|
||||
return b.Substring(11);
|
||||
|
||||
if (b.StartsWith("refs/remotes/", StringComparison.Ordinal))
|
||||
return b.Substring(13);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
private bool _isLocked = false;
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,7 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Watermark="{DynamicResource Text.Remote.Name.Placeholder}"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Text="{Binding Name, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.AddSubmodule"
|
||||
x:DataType="vm:AddSubmodule">
|
||||
@@ -28,8 +27,7 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Watermark="{DynamicResource Text.RepositoryURL}"
|
||||
Text="{Binding Url, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Text="{Binding Url, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.AddToIgnore"
|
||||
x:DataType="vm:AddToIgnore">
|
||||
@@ -27,8 +26,7 @@
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding Pattern, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True">
|
||||
Text="{Binding Pattern, Mode=TwoWay}">
|
||||
<TextBox.InnerLeftContent>
|
||||
<Path Width="12" Height="12" Margin="6,0,2,0" Data="{StaticResource Icons.Pattern}" Fill="{DynamicResource Brush.FG2}"/>
|
||||
</TextBox.InnerLeftContent>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.Apply"
|
||||
x:DataType="vm:Apply">
|
||||
@@ -29,8 +28,7 @@
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Watermark="{DynamicResource Text.Apply.File.Placeholder}"
|
||||
Text="{Binding PatchFile, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True">
|
||||
Text="{Binding PatchFile, Mode=TwoWay}">
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button" Width="30" Height="30" Click="SelectPatchFile">
|
||||
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.Archive"
|
||||
@@ -60,8 +59,7 @@
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Watermark="{DynamicResource Text.Archive.File.Placeholder}"
|
||||
Text="{Binding SaveFile, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True">
|
||||
Text="{Binding SaveFile, Mode=TwoWay}">
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button" Width="30" Height="30" Click="SelectOutputFile">
|
||||
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||
|
||||
@@ -46,8 +46,7 @@
|
||||
Focusable="True"
|
||||
PasswordChar="*"
|
||||
RevealPassword="{Binding #ToggleShowPassword.IsChecked, Mode=OneWay}"
|
||||
HorizontalAlignment="Stretch"
|
||||
v:AutoFocusBehaviour.IsEnabled="True">
|
||||
HorizontalAlignment="Stretch">
|
||||
<TextBox.InnerRightContent>
|
||||
<ToggleButton Grid.Column="6"
|
||||
x:Name="ToggleShowPassword"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace SourceGit.Views
|
||||
@@ -10,6 +12,12 @@ namespace SourceGit.Views
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
TxtPassphrase.Focus(NavigationMethod.Directional);
|
||||
}
|
||||
|
||||
private void CloseWindow(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
Console.Out.WriteLine("No passphrase entered.");
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class AutoFocusBehaviour : AvaloniaObject
|
||||
{
|
||||
public static readonly AttachedProperty<bool> IsEnabledProperty =
|
||||
AvaloniaProperty.RegisterAttached<AutoFocusBehaviour, TextBox, bool>("IsEnabled");
|
||||
|
||||
static AutoFocusBehaviour()
|
||||
{
|
||||
IsEnabledProperty.Changed.AddClassHandler<TextBox>(OnIsEnabledChanged);
|
||||
}
|
||||
|
||||
public static bool GetIsEnabled(AvaloniaObject elem)
|
||||
{
|
||||
return elem.GetValue(IsEnabledProperty);
|
||||
}
|
||||
|
||||
public static void SetIsEnabled(AvaloniaObject elem, bool value)
|
||||
{
|
||||
elem.SetValue(IsEnabledProperty, value);
|
||||
}
|
||||
|
||||
private static void OnIsEnabledChanged(TextBox elem, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (GetIsEnabled(elem))
|
||||
{
|
||||
elem.AttachedToVisualTree += (o, _) =>
|
||||
{
|
||||
if (o is TextBox box)
|
||||
{
|
||||
box.Focus(NavigationMethod.Directional);
|
||||
box.CaretIndex = box.Text?.Length ?? 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,8 @@ namespace SourceGit.Views
|
||||
var typeface = view.CreateTypeface();
|
||||
var underlinePen = new Pen(Brushes.DarkOrange);
|
||||
var width = Bounds.Width;
|
||||
var lineHeight = view.DefaultLineHeight;
|
||||
var pixelHeight = PixelSnapHelpers.GetPixelSize(view).Height;
|
||||
|
||||
foreach (var line in view.VisualLines)
|
||||
{
|
||||
@@ -50,8 +52,8 @@ namespace SourceGit.Views
|
||||
|
||||
var info = _editor.BlameData.LineInfos[lineNumber - 1];
|
||||
var x = 0.0;
|
||||
var y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextTop) - view.VerticalOffset;
|
||||
if (!info.IsFirstInGroup && y > view.DefaultLineHeight * 0.6)
|
||||
var y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.LineMiddle) - view.VerticalOffset;
|
||||
if (!info.IsFirstInGroup && y > lineHeight)
|
||||
continue;
|
||||
|
||||
var shaLink = new FormattedText(
|
||||
@@ -61,8 +63,10 @@ namespace SourceGit.Views
|
||||
typeface,
|
||||
_editor.FontSize,
|
||||
Brushes.DarkOrange);
|
||||
context.DrawText(shaLink, new Point(x, y));
|
||||
context.DrawLine(underlinePen, new Point(x, y + shaLink.Baseline + 2), new Point(x + shaLink.Width, y + shaLink.Baseline + 2));
|
||||
var shaLinkTop = y - shaLink.Height * 0.5;
|
||||
var underlineY = PixelSnapHelpers.PixelAlign(y + shaLink.Height * 0.5 + 0.5, pixelHeight);
|
||||
context.DrawText(shaLink, new Point(x, shaLinkTop));
|
||||
context.DrawLine(underlinePen, new Point(x, underlineY), new Point(x + shaLink.Width, underlineY));
|
||||
x += shaLink.Width + 8;
|
||||
|
||||
var author = new FormattedText(
|
||||
@@ -72,16 +76,19 @@ namespace SourceGit.Views
|
||||
typeface,
|
||||
_editor.FontSize,
|
||||
_editor.Foreground);
|
||||
context.DrawText(author, new Point(x, y));
|
||||
var authorTop = y - author.Height * 0.5;
|
||||
context.DrawText(author, new Point(x, authorTop));
|
||||
|
||||
var timeStr = Models.DateTimeFormat.Format(info.Timestamp, true);
|
||||
var time = new FormattedText(
|
||||
info.Time,
|
||||
timeStr,
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
_editor.FontSize,
|
||||
_editor.Foreground);
|
||||
context.DrawText(time, new Point(width - time.Width, y));
|
||||
var timeTop = y - time.Height * 0.5;
|
||||
context.DrawText(time, new Point(width - time.Width, timeTop));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,8 +131,9 @@ namespace SourceGit.Views
|
||||
_editor.Foreground);
|
||||
x += author.Width + 8;
|
||||
|
||||
var timeStr = Models.DateTimeFormat.Format(info.Timestamp, true);
|
||||
var time = new FormattedText(
|
||||
info.Time,
|
||||
timeStr,
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
@@ -150,6 +158,7 @@ namespace SourceGit.Views
|
||||
{
|
||||
var pos = e.GetPosition(this);
|
||||
var typeface = view.CreateTypeface();
|
||||
var lineHeight = view.DefaultLineHeight;
|
||||
|
||||
foreach (var line in view.VisualLines)
|
||||
{
|
||||
@@ -161,7 +170,7 @@ namespace SourceGit.Views
|
||||
break;
|
||||
|
||||
var info = _editor.BlameData.LineInfos[lineNumber - 1];
|
||||
var y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextTop) - view.VerticalOffset;
|
||||
var y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.LineTop) - view.VerticalOffset;
|
||||
var shaLink = new FormattedText(
|
||||
info.CommitSHA,
|
||||
CultureInfo.CurrentCulture,
|
||||
@@ -170,7 +179,7 @@ namespace SourceGit.Views
|
||||
_editor.FontSize,
|
||||
Brushes.DarkOrange);
|
||||
|
||||
var rect = new Rect(0, y, shaLink.Width, shaLink.Height);
|
||||
var rect = new Rect(0, y, shaLink.Width, lineHeight);
|
||||
if (rect.Contains(pos))
|
||||
{
|
||||
Cursor = Cursor.Parse("Hand");
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.BlameCommandPalette"
|
||||
x:DataType="vm:BlameCommandPalette">
|
||||
<Grid RowDefinitions="Auto,Auto">
|
||||
<Grid RowDefinitions="Auto,Auto,Auto">
|
||||
<v:RepositoryCommandPaletteTextBox Grid.Row="0"
|
||||
x:Name="FilterTextBox"
|
||||
Height="24"
|
||||
@@ -50,11 +50,17 @@
|
||||
</Button>
|
||||
</TextBox.InnerRightContent>
|
||||
</v:RepositoryCommandPaletteTextBox>
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Margin="6,12,0,0"
|
||||
Text="{DynamicResource Text.CommandPalette.RevisionFiles}"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<ListBox Grid.Row="1"
|
||||
<ListBox Grid.Row="2"
|
||||
x:Name="FileListBox"
|
||||
MaxHeight="250"
|
||||
Margin="4,8,4,0"
|
||||
MaxHeight="360"
|
||||
Margin="4,8"
|
||||
BorderThickness="0"
|
||||
SelectionMode="Single"
|
||||
Background="Transparent"
|
||||
@@ -88,7 +94,7 @@
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="x:String">
|
||||
<Grid ColumnDefinitions="Auto,*" Background="Transparent" Tapped="OnItemTapped">
|
||||
<Grid ColumnDefinitions="Auto,*" Background="Transparent" Tapped="OnItemTapped" ToolTip.Tip="{Binding}">
|
||||
<Path Grid.Column="0"
|
||||
Width="12" Height="12"
|
||||
Data="{StaticResource Icons.File}"
|
||||
|
||||
@@ -303,6 +303,15 @@ namespace SourceGit.Views
|
||||
remove { RemoveHandler(RowsChangedEvent, value); }
|
||||
}
|
||||
|
||||
public static readonly RoutedEvent<RoutedEventArgs> SearchRequestedEvent =
|
||||
RoutedEvent.Register<BranchTree, RoutedEventArgs>(nameof(SearchRequested), RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
|
||||
|
||||
public event EventHandler<RoutedEventArgs> SearchRequested
|
||||
{
|
||||
add { AddHandler(SearchRequestedEvent, value); }
|
||||
remove { RemoveHandler(SearchRequestedEvent, value); }
|
||||
}
|
||||
|
||||
public BranchTree()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -566,6 +575,13 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnTreeKeyDown(object _, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.F && e.KeyModifiers == (OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(SearchRequestedEvent));
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Key is not (Key.Delete or Key.Back))
|
||||
return;
|
||||
|
||||
@@ -722,9 +738,7 @@ namespace SourceGit.Views
|
||||
compareWith.Icon = App.CreateMenuIcon("Icons.Compare");
|
||||
compareWith.Click += (_, _) =>
|
||||
{
|
||||
var launcher = App.GetLauncher();
|
||||
if (launcher != null)
|
||||
launcher.OpenCommandPalette(new ViewModels.CompareCommandPalette(launcher, repo, branch));
|
||||
new ViewModels.CompareCommandPalette(repo, branch).Open();
|
||||
};
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
menu.Items.Add(compareWith);
|
||||
@@ -847,9 +861,7 @@ namespace SourceGit.Views
|
||||
compareWith.Icon = App.CreateMenuIcon("Icons.Compare");
|
||||
compareWith.Click += (_, _) =>
|
||||
{
|
||||
var launcher = App.GetLauncher();
|
||||
if (launcher != null)
|
||||
launcher.OpenCommandPalette(new ViewModels.CompareCommandPalette(launcher, repo, branch));
|
||||
new ViewModels.CompareCommandPalette(repo, branch).Open();
|
||||
};
|
||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
menu.Items.Add(compareWithCurrent);
|
||||
@@ -1155,9 +1167,7 @@ namespace SourceGit.Views
|
||||
compareWith.Icon = App.CreateMenuIcon("Icons.Compare");
|
||||
compareWith.Click += (_, _) =>
|
||||
{
|
||||
var launcher = App.GetLauncher();
|
||||
if (launcher != null)
|
||||
launcher.OpenCommandPalette(new ViewModels.CompareCommandPalette(launcher, repo, branch));
|
||||
new ViewModels.CompareCommandPalette(repo, branch).Open();
|
||||
};
|
||||
|
||||
menu.Items.Add(pull);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.CheckoutCommandPalette"
|
||||
x:DataType="vm:CheckoutCommandPalette">
|
||||
<Grid RowDefinitions="Auto,Auto">
|
||||
<Grid RowDefinitions="Auto,Auto,Auto">
|
||||
<v:RepositoryCommandPaletteTextBox Grid.Row="0"
|
||||
x:Name="FilterTextBox"
|
||||
Height="24"
|
||||
@@ -52,10 +52,16 @@
|
||||
</TextBox.InnerRightContent>
|
||||
</v:RepositoryCommandPaletteTextBox>
|
||||
|
||||
<ListBox Grid.Row="1"
|
||||
<TextBlock Grid.Row="1"
|
||||
Margin="6,12,0,0"
|
||||
Text="{DynamicResource Text.CommandPalette.Branches}"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<ListBox Grid.Row="2"
|
||||
x:Name="BranchListBox"
|
||||
MaxHeight="250"
|
||||
Margin="4,8,4,0"
|
||||
MaxHeight="360"
|
||||
Margin="4,8"
|
||||
BorderThickness="0"
|
||||
SelectionMode="Single"
|
||||
Background="Transparent"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.Clone"
|
||||
x:DataType="vm:Clone">
|
||||
@@ -27,8 +26,7 @@
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding Remote, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Text="{Binding Remote, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right"
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
<Run Text="{Binding Author.Email, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
<TextBlock Text="{Binding AuthorTimeStr}"
|
||||
Margin="2,0,0,0"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
<v:DateTimePresenter Margin="2,0,0,0"
|
||||
Timestamp="{Binding AuthorTime}"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -43,10 +43,10 @@
|
||||
<Run Text="{Binding Committer.Email, Mode=OneWay}"/>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
<TextBlock Text="{Binding CommitterTimeStr}"
|
||||
Margin="2,0,0,0"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
<v:DateTimePresenter Margin="2,0,0,0"
|
||||
Timestamp="{Binding CommitterTime}"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=DefaultFontSize, Converter={x:Static c:DoubleConverters.Decrease}}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UniformGrid>
|
||||
@@ -127,7 +127,10 @@
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<v:Avatar Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Author.Name}" Margin="8,0,0,0"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
|
||||
<v:DateTimePresenter Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Timestamp="{Binding CommitterTime}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Margin="0,8,0,0" Text="{Binding Subject}" TextWrapping="Wrap"/>
|
||||
@@ -171,7 +174,10 @@
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<v:Avatar Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Author.Name}" Margin="8,0,0,0"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
|
||||
<v:DateTimePresenter Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Timestamp="{Binding CommitterTime}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Margin="0,8,0,0" Text="{Binding Subject}" TextWrapping="Wrap"/>
|
||||
@@ -213,7 +219,10 @@
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<v:Avatar Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Author.Name}" Margin="8,0,0,0"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
|
||||
<v:DateTimePresenter Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
Timestamp="{Binding CommitterTime}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Margin="0,8,0,0" Text="{Binding Subject}" TextWrapping="Wrap"/>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<!-- Search & Display Mode -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto">
|
||||
<TextBox Grid.Column="0"
|
||||
x:Name="CommitChangeSearchBox"
|
||||
Height="26"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Background="Transparent"
|
||||
@@ -67,7 +68,8 @@
|
||||
<GridSplitter Grid.Column="1"
|
||||
MinWidth="1"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Background="Transparent"/>
|
||||
Background="Transparent"
|
||||
Focusable="False"/>
|
||||
|
||||
<Grid Grid.Column="2">
|
||||
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace SourceGit.Views
|
||||
if (sender is not ChangeCollectionView { SelectedChanges: { Count: > 0 } selectedChanges } view)
|
||||
return;
|
||||
|
||||
if (e.Key == Key.C &&
|
||||
e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control))
|
||||
var cmdKey = OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control;
|
||||
if (e.Key == Key.C && e.KeyModifiers.HasFlag(cmdKey))
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
var copyAbsPath = e.KeyModifiers.HasFlag(KeyModifiers.Shift);
|
||||
@@ -65,6 +65,11 @@ namespace SourceGit.Views
|
||||
await App.CopyTextAsync(builder.ToString());
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.F && e.KeyModifiers == cmdKey)
|
||||
{
|
||||
CommitChangeSearchBox.Focus();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,12 +37,20 @@
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="8">
|
||||
<v:CommitMessageToolBox x:Name="Editor" Height="400"/>
|
||||
<Button Classes="flat primary"
|
||||
Width="80"
|
||||
Margin="0,8,0,4"
|
||||
Content="{DynamicResource Text.Sure}"
|
||||
Click="SaveAndClose"
|
||||
HorizontalAlignment="Center"/>
|
||||
|
||||
<StackPanel Margin="0,8,0,4" Orientation="Horizontal" HorizontalAlignment="Center" Spacing="8">
|
||||
<Button Classes="flat primary"
|
||||
Width="80"
|
||||
Content="{DynamicResource Text.Sure}"
|
||||
Click="SaveAndClose"
|
||||
HorizontalAlignment="Center"/>
|
||||
<Button Classes="flat"
|
||||
Width="80"
|
||||
Content="{DynamicResource Text.Cancel}"
|
||||
Click="CancelAndClose"
|
||||
HotKey="Escape"
|
||||
HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</v:ChromelessWindow>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace SourceGit.Views
|
||||
@@ -15,7 +16,6 @@ namespace SourceGit.Views
|
||||
|
||||
public CommitMessageEditor()
|
||||
{
|
||||
CloseOnESC = true;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
@@ -67,12 +67,17 @@ namespace SourceGit.Views
|
||||
private void SaveAndClose(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
_onSave?.Invoke(Editor.CommitMessage);
|
||||
_exitCode = 0;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void CancelAndClose(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
_exitCode = -1;
|
||||
Close();
|
||||
}
|
||||
|
||||
private Action<string> _onSave = null;
|
||||
private bool _shouldExitApp = true;
|
||||
private int _exitCode = -1;
|
||||
private int _exitCode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,10 +279,10 @@ namespace SourceGit.Views
|
||||
_isEditing = false;
|
||||
|
||||
var caretOffset = CaretOffset;
|
||||
var start = caretOffset;
|
||||
for (; start > 0; start--)
|
||||
var lineStart = caretOffset;
|
||||
for (; lineStart > 0; lineStart--)
|
||||
{
|
||||
var ch = Text[start - 1];
|
||||
var ch = Text[lineStart - 1];
|
||||
if (ch == '\n')
|
||||
break;
|
||||
|
||||
@@ -290,18 +290,18 @@ namespace SourceGit.Views
|
||||
return;
|
||||
}
|
||||
|
||||
if (caretOffset < start + 2)
|
||||
if (lineStart == 0 || caretOffset < lineStart + 2)
|
||||
{
|
||||
_completionWnd?.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
var word = Text.Substring(start, caretOffset - start);
|
||||
var word = Text.Substring(lineStart, caretOffset - lineStart);
|
||||
var matches = new List<CommitMessageCodeCompletionData>();
|
||||
foreach (var keyword in _keywords)
|
||||
foreach (var t in _trailers)
|
||||
{
|
||||
if (keyword.StartsWith(word, StringComparison.OrdinalIgnoreCase) && keyword.Length != word.Length)
|
||||
matches.Add(new(keyword));
|
||||
if (t.StartsWith(word, StringComparison.OrdinalIgnoreCase) && t.Length != word.Length)
|
||||
matches.Add(new(t));
|
||||
}
|
||||
|
||||
if (matches.Count > 0)
|
||||
@@ -315,7 +315,7 @@ namespace SourceGit.Views
|
||||
|
||||
_completionWnd.CompletionList.CompletionData.Clear();
|
||||
_completionWnd.CompletionList.CompletionData.AddRange(matches);
|
||||
_completionWnd.StartOffset = start;
|
||||
_completionWnd.StartOffset = lineStart;
|
||||
_completionWnd.EndOffset = caretOffset;
|
||||
}
|
||||
else
|
||||
@@ -377,7 +377,23 @@ namespace SourceGit.Views
|
||||
SetCurrentValue(ColumnProperty, col);
|
||||
}
|
||||
|
||||
private readonly List<string> _keywords = ["Acked-by: ", "Co-authored-by: ", "Reviewed-by: ", "Signed-off-by: ", "on-behalf-of: @", "BREAKING CHANGE: ", "Refs: "];
|
||||
private readonly List<string> _trailers =
|
||||
[
|
||||
"Acked-by: ",
|
||||
"BREAKING CHANGE: ",
|
||||
"Co-authored-by: ",
|
||||
"Fixes: ",
|
||||
"Helped-by: ",
|
||||
"Issue: ",
|
||||
"Milestone: ",
|
||||
"on-behalf-of: @",
|
||||
"Reference-to: ",
|
||||
"Refs: ",
|
||||
"Reviewed-by: ",
|
||||
"See-also: ",
|
||||
"Signed-off-by: ",
|
||||
];
|
||||
|
||||
private bool _isEditing = false;
|
||||
private int _subjectEndLine = 0;
|
||||
private CompletionWindow _completionWnd = null;
|
||||
@@ -552,6 +568,7 @@ namespace SourceGit.Views
|
||||
if (vm.Staged == null || vm.Staged.Count == 0)
|
||||
{
|
||||
App.RaiseException(repo.FullPath, "No files added to commit!");
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -559,12 +576,14 @@ namespace SourceGit.Views
|
||||
if (services.Count == 0)
|
||||
{
|
||||
App.RaiseException(repo.FullPath, "Bad configuration for OpenAI");
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (services.Count == 1)
|
||||
{
|
||||
await App.ShowDialog(new ViewModels.AIAssistant(repo, services[0], vm.Staged));
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,15 @@ namespace SourceGit.Views
|
||||
set => SetValue(ShowAsDateTimeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> Use24HoursProperty =
|
||||
AvaloniaProperty.Register<CommitTimeTextBlock, bool>(nameof(Use24Hours), true);
|
||||
|
||||
public bool Use24Hours
|
||||
{
|
||||
get => GetValue(Use24HoursProperty);
|
||||
set => SetValue(Use24HoursProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<int> DateTimeFormatProperty =
|
||||
AvaloniaProperty.Register<CommitTimeTextBlock, int>(nameof(DateTimeFormat));
|
||||
|
||||
@@ -62,7 +71,7 @@ namespace SourceGit.Views
|
||||
HorizontalAlignment = HorizontalAlignment.Center;
|
||||
}
|
||||
}
|
||||
else if (change.Property == DateTimeFormatProperty)
|
||||
else if (change.Property == DateTimeFormatProperty || change.Property == Use24HoursProperty)
|
||||
{
|
||||
if (ShowAsDateTime)
|
||||
SetCurrentValue(TextProperty, GetDisplayText());
|
||||
@@ -121,10 +130,10 @@ namespace SourceGit.Views
|
||||
if (DataContext is not Models.Commit commit)
|
||||
return string.Empty;
|
||||
|
||||
if (ShowAsDateTime)
|
||||
return UseAuthorTime ? commit.AuthorTimeStr : commit.CommitterTimeStr;
|
||||
|
||||
var timestamp = UseAuthorTime ? commit.AuthorTime : commit.CommitterTime;
|
||||
if (ShowAsDateTime)
|
||||
return Models.DateTimeFormat.Format(timestamp);
|
||||
|
||||
var now = DateTime.Now;
|
||||
var localTime = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime();
|
||||
var span = now - localTime;
|
||||
|
||||
@@ -53,8 +53,16 @@
|
||||
<TextBlock Text="{Binding BaseName}" Margin="4,0" Foreground="#FFF2F2F2"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<TextBlock Grid.Column="3" Text="{Binding BaseHead.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0" TextDecorations="Underline" Cursor="Hand" PointerPressed="OnPressedSHA"/>
|
||||
<TextBlock Grid.Column="4" Text="{Binding BaseHead.CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
|
||||
<TextBlock Grid.Column="3"
|
||||
Text="{Binding BaseHead.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
|
||||
Foreground="DarkOrange" Margin="8,0,0,0"
|
||||
TextDecorations="Underline"
|
||||
Cursor="Hand"
|
||||
PointerPressed="OnPressedSHA"/>
|
||||
<v:DateTimePresenter Grid.Column="4"
|
||||
Margin="8,0,0,0"
|
||||
Timestamp="{Binding BaseHead.CommitterTime}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="1" Text="{Binding BaseHead.Subject}" VerticalAlignment="Bottom"/>
|
||||
@@ -81,7 +89,10 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<TextBlock Grid.Column="3" Text="{Binding ToHead.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0" TextDecorations="Underline" Cursor="Hand" PointerPressed="OnPressedSHA"/>
|
||||
<TextBlock Grid.Column="4" Text="{Binding ToHead.CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
|
||||
<v:DateTimePresenter Grid.Column="4"
|
||||
Margin="8,0,0,0"
|
||||
Timestamp="{Binding ToHead.CommitterTime}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="1" Text="{Binding ToHead.Subject}" VerticalAlignment="Bottom"/>
|
||||
@@ -103,6 +114,7 @@
|
||||
<!-- Search & Display Mode -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,18">
|
||||
<TextBox Grid.Column="0"
|
||||
x:Name="ChangeSearchBox"
|
||||
Height="26"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Background="Transparent"
|
||||
@@ -158,7 +170,8 @@
|
||||
<GridSplitter Grid.Column="1"
|
||||
MinWidth="1"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Background="Transparent"/>
|
||||
Background="Transparent"
|
||||
Focusable="False"/>
|
||||
|
||||
<Grid Grid.Column="2">
|
||||
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
|
||||
|
||||
@@ -218,7 +218,8 @@ namespace SourceGit.Views
|
||||
if (sender is not ChangeCollectionView { SelectedChanges: { Count: > 0 } selectedChanges })
|
||||
return;
|
||||
|
||||
if (e.KeyModifiers.HasFlag(OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control) && e.Key == Key.C)
|
||||
var cmdKey = OperatingSystem.IsMacOS() ? KeyModifiers.Meta : KeyModifiers.Control;
|
||||
if (e.Key == Key.C && e.KeyModifiers.HasFlag(cmdKey))
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
var copyAbsPath = e.KeyModifiers.HasFlag(KeyModifiers.Shift);
|
||||
@@ -235,6 +236,11 @@ namespace SourceGit.Views
|
||||
await App.CopyTextAsync(builder.ToString());
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.F && e.KeyModifiers == cmdKey)
|
||||
{
|
||||
ChangeSearchBox.Focus();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.CompareCommandPalette"
|
||||
x:DataType="vm:CompareCommandPalette">
|
||||
<Grid RowDefinitions="Auto,Auto">
|
||||
<Grid RowDefinitions="Auto,Auto,Auto">
|
||||
<v:RepositoryCommandPaletteTextBox Grid.Row="0"
|
||||
x:Name="FilterTextBox"
|
||||
Height="24"
|
||||
@@ -64,10 +64,16 @@
|
||||
</TextBox.InnerRightContent>
|
||||
</v:RepositoryCommandPaletteTextBox>
|
||||
|
||||
<ListBox Grid.Row="1"
|
||||
<TextBlock Grid.Row="1"
|
||||
Margin="6,12,0,0"
|
||||
Text="{DynamicResource Text.CommandPalette.BranchesAndTags}"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<ListBox Grid.Row="2"
|
||||
x:Name="RefsListBox"
|
||||
MaxHeight="250"
|
||||
Margin="4,8,4,0"
|
||||
MaxHeight="360"
|
||||
Margin="4,8"
|
||||
BorderThickness="0"
|
||||
SelectionMode="Single"
|
||||
Background="Transparent"
|
||||
|
||||
@@ -37,11 +37,20 @@
|
||||
|
||||
<!-- Body -->
|
||||
<Border Grid.Row="1" Margin="16">
|
||||
<TextBlock x:Name="TxtMessage" MaxWidth="520" TextWrapping="Wrap"/>
|
||||
<TextBlock x:Name="TxtMessage" TextWrapping="NoWrap"/>
|
||||
</Border>
|
||||
|
||||
<!-- Buttons -->
|
||||
<StackPanel Grid.Row="2" Margin="0,0,0,16" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<StackPanel Grid.Row="2" Margin="32,0,32,16" Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<Button Classes="flat"
|
||||
x:Name="BtnStageSelectedAndCommit"
|
||||
Height="30"
|
||||
Margin="4,0"
|
||||
Click="StageSelectedThenCommit"
|
||||
Content="{DynamicResource Text.ConfirmEmptyCommit.StageSelectedThenCommit}"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"/>
|
||||
|
||||
<Button Classes="flat"
|
||||
x:Name="BtnStageAllAndCommit"
|
||||
Height="30"
|
||||
|
||||
@@ -9,6 +9,11 @@ namespace SourceGit.Views
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void StageSelectedThenCommit(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
Close(Models.ConfirmEmptyCommitResult.StageSelectedAndCommit);
|
||||
}
|
||||
|
||||
private void StageAllThenCommit(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
Close(Models.ConfirmEmptyCommitResult.StageAllAndCommit);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
Text="{DynamicResource Text.CreateBranch.Title}"/>
|
||||
</StackPanel>
|
||||
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,Auto">
|
||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,Auto,Auto">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" MinWidth="140"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
@@ -65,8 +65,7 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.CreateBranch.Name.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Watermark="{DynamicResource Text.CreateBranch.Name.Placeholder}"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.CreateGroup"
|
||||
x:DataType="vm:CreateGroup">
|
||||
@@ -20,7 +19,7 @@
|
||||
|
||||
<Grid Margin="8,16,0,0" Height="28" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" Margin="8,0" Text="{DynamicResource Text.Name}"/>
|
||||
<TextBox Grid.Column="1" CornerRadius="3" v:AutoFocusBehaviour.IsEnabled="True" Text="{Binding Name, Mode=TwoWay}"/>
|
||||
<TextBox Grid.Column="1" CornerRadius="3" Text="{Binding Name, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -53,8 +53,7 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding TagName, Mode=TwoWay}"
|
||||
Watermark="{DynamicResource Text.CreateTag.Name.Placeholder}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Watermark="{DynamicResource Text.CreateTag.Name.Placeholder}"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
|
||||
80
src/Views/DateTimePresenter.cs
Normal file
80
src/Views/DateTimePresenter.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class DateTimePresenter : TextBlock
|
||||
{
|
||||
public static readonly StyledProperty<bool> ShowDateOnlyProperty =
|
||||
AvaloniaProperty.Register<DateTimePresenter, bool>(nameof(ShowDateOnly), false);
|
||||
|
||||
public bool ShowDateOnly
|
||||
{
|
||||
get => GetValue(ShowDateOnlyProperty);
|
||||
set => SetValue(ShowDateOnlyProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> Use24HoursProperty =
|
||||
AvaloniaProperty.Register<DateTimePresenter, bool>(nameof(Use24Hours), true);
|
||||
|
||||
public bool Use24Hours
|
||||
{
|
||||
get => GetValue(Use24HoursProperty);
|
||||
set => SetValue(Use24HoursProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<int> DateTimeFormatProperty =
|
||||
AvaloniaProperty.Register<DateTimePresenter, int>(nameof(DateTimeFormat));
|
||||
|
||||
public int DateTimeFormat
|
||||
{
|
||||
get => GetValue(DateTimeFormatProperty);
|
||||
set => SetValue(DateTimeFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<ulong> TimestampProperty =
|
||||
AvaloniaProperty.Register<DateTimePresenter, ulong>(nameof(Timestamp), 0);
|
||||
|
||||
public ulong Timestamp
|
||||
{
|
||||
get => GetValue(TimestampProperty);
|
||||
set => SetValue(TimestampProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(TextBlock);
|
||||
|
||||
public DateTimePresenter()
|
||||
{
|
||||
Bind(Use24HoursProperty, new Binding()
|
||||
{
|
||||
Mode = BindingMode.OneWay,
|
||||
Source = ViewModels.Preferences.Instance,
|
||||
Path = "Use24Hours"
|
||||
});
|
||||
|
||||
Bind(DateTimeFormatProperty, new Binding()
|
||||
{
|
||||
Mode = BindingMode.OneWay,
|
||||
Source = ViewModels.Preferences.Instance,
|
||||
Path = "DateTimeFormat"
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == ShowDateOnlyProperty ||
|
||||
change.Property == Use24HoursProperty ||
|
||||
change.Property == DateTimeFormatProperty ||
|
||||
change.Property == TimestampProperty)
|
||||
{
|
||||
var text = Models.DateTimeFormat.Format(Timestamp, ShowDateOnly);
|
||||
SetCurrentValue(TextProperty, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,13 +265,14 @@
|
||||
<TextBlock Text="{DynamicResource Text.Diff.Submodule.Deleted}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||
</Border>
|
||||
|
||||
<Border Margin="0,8,0,0" IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<Border Margin="0,8"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
|
||||
Background="{DynamicResource Brush.Window}"
|
||||
IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<ContentControl Content="{Binding Old}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="m:RevisionSubmodule">
|
||||
<Border Margin="0,0,0,8" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Background="{DynamicResource Brush.Window}">
|
||||
<v:CommitBaseInfo Margin="0,4,8,6" Content="{Binding Commit}" FullMessage="{Binding FullMessage}"/>
|
||||
</Border>
|
||||
<v:CommitBaseInfo Margin="0,4,8,6" Content="{Binding Commit}" FullMessage="{Binding FullMessage}"/>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
</ContentControl>
|
||||
@@ -290,7 +291,10 @@
|
||||
<TextBlock Text="{DynamicResource Text.Diff.Submodule.New}" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||
</Border>
|
||||
|
||||
<Border Margin="0,8,0,0" BorderThickness="1" BorderBrush="Green" Background="{DynamicResource Brush.Window}" IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<Border Margin="0,8"
|
||||
BorderThickness="1" BorderBrush="Green"
|
||||
Background="{DynamicResource Brush.Window}"
|
||||
IsVisible="{Binding New, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<ContentControl Content="{Binding New}">
|
||||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="m:RevisionSubmodule">
|
||||
|
||||
@@ -94,7 +94,12 @@
|
||||
TextDecorations="Underline"
|
||||
Margin="8,0,0,0"
|
||||
PointerPressed="OnPressCommitSHA"/>
|
||||
<TextBlock Grid.Column="3" Text="{Binding AuthorTimeShortStr}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Right"/>
|
||||
<v:DateTimePresenter Grid.Column="3"
|
||||
Margin="8,0,0,0"
|
||||
ShowDateOnly="True"
|
||||
Timestamp="{Binding AuthorTime}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="1" Background="Transparent" DataContextChanged="OnCommitSubjectDataContextChanged" PointerMoved="OnCommitSubjectPointerMoved">
|
||||
@@ -117,7 +122,8 @@
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
BorderThickness="1,0,0,0"
|
||||
BorderBrush="{DynamicResource Brush.Border0}"/>
|
||||
BorderBrush="{DynamicResource Brush.Border0}"
|
||||
Focusable="False"/>
|
||||
|
||||
<!-- Commit Detail -->
|
||||
<Border Grid.Column="2" Padding="0,4" IsVisible="{Binding !IsLoading}">
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.EditRemote"
|
||||
x:DataType="vm:EditRemote">
|
||||
@@ -28,8 +27,7 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Watermark="{DynamicResource Text.Remote.Name.Placeholder}"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Text="{Binding Name, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.EditRepositoryNode"
|
||||
x:DataType="vm:EditRepositoryNode">
|
||||
@@ -32,7 +31,7 @@
|
||||
</Grid>
|
||||
<Grid Height="28" Margin="8,4,0,0" ColumnDefinitions="120,*">
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" Margin="0,0,8,0" Text="{DynamicResource Text.EditRepositoryNode.Name}"/>
|
||||
<TextBox Grid.Column="1" CornerRadius="3" Text="{Binding Name, Mode=TwoWay}" v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
<TextBox Grid.Column="1" CornerRadius="3" Text="{Binding Name, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
<Grid Height="28" Margin="8,4,0,0" ColumnDefinitions="120,*" IsVisible="{Binding IsRepository}">
|
||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" Margin="0,0,8,0" Text="{DynamicResource Text.EditRepositoryNode.Bookmark}"/>
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.ExecuteCustomAction"
|
||||
x:DataType="vm:ExecuteCustomAction"
|
||||
Loaded="OnLoaded">
|
||||
x:DataType="vm:ExecuteCustomAction">
|
||||
<StackPanel Orientation="Vertical" Margin="8,0">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path Width="16" Height="16"
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
@@ -15,19 +13,6 @@ namespace SourceGit.Views
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var inputs = this.GetVisualDescendants();
|
||||
foreach (var input in inputs)
|
||||
{
|
||||
if (input is InputElement { Focusable: true, IsTabStop: true } focusable)
|
||||
{
|
||||
focusable.Focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void SelectPath(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
|
||||
124
src/Views/ExecuteCustomActionCommandPalette.axaml
Normal file
124
src/Views/ExecuteCustomActionCommandPalette.axaml
Normal file
@@ -0,0 +1,124 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
xmlns:c="using:SourceGit.Converters"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.ExecuteCustomActionCommandPalette"
|
||||
x:DataType="vm:ExecuteCustomActionCommandPalette">
|
||||
<Grid RowDefinitions="Auto,Auto,Auto">
|
||||
<v:RepositoryCommandPaletteTextBox Grid.Row="0"
|
||||
x:Name="FilterTextBox"
|
||||
Height="24"
|
||||
Margin="4,8,4,0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="12"
|
||||
Text="{Binding Filter, Mode=TwoWay}"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
VerticalContentAlignment="Center">
|
||||
<TextBox.InnerLeftContent>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path Width="14" Height="14"
|
||||
Margin="6,0,0,0"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
Data="{StaticResource Icons.Search}"/>
|
||||
<Border BorderThickness="0"
|
||||
Background="{DynamicResource Brush.Badge}"
|
||||
Height="18"
|
||||
CornerRadius="4"
|
||||
Margin="4,0,0,0" Padding="4,0">
|
||||
<TextBlock Text="{DynamicResource Text.Repository.CustomActions}"
|
||||
Foreground="Black"
|
||||
FontWeight="Bold"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</TextBox.InnerLeftContent>
|
||||
|
||||
<TextBox.InnerRightContent>
|
||||
<Button Classes="icon_button"
|
||||
Width="16"
|
||||
Margin="0,0,6,0"
|
||||
Command="{Binding ClearFilter}"
|
||||
IsVisible="{Binding Filter, 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>
|
||||
</v:RepositoryCommandPaletteTextBox>
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Margin="6,12,0,0"
|
||||
Text="{DynamicResource Text.CommandPalette.RepositoryActions}"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<ListBox Grid.Row="2"
|
||||
x:Name="ActionListBox"
|
||||
MaxHeight="360"
|
||||
Margin="4,8"
|
||||
BorderThickness="0"
|
||||
SelectionMode="Single"
|
||||
Background="Transparent"
|
||||
Focusable="True"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
ItemsSource="{Binding VisibleActions, Mode=OneWay}"
|
||||
SelectedItem="{Binding Selected, Mode=TwoWay}"
|
||||
IsVisible="{Binding VisibleActions, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}">
|
||||
<ListBox.Styles>
|
||||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="Padding" Value="8,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>
|
||||
<VirtualizingStackPanel Orientation="Vertical"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:ExecuteCustomActionCommandPaletteCmd">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto" Background="Transparent" Tapped="OnItemTapped">
|
||||
<Path Grid.Column="0"
|
||||
Width="12" Height="12"
|
||||
Data="{StaticResource Icons.Action}"
|
||||
IsHitTestVisible="False"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
Margin="4,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
IsHitTestVisible="False"
|
||||
Text="{Binding Name, Mode=OneWay}"/>
|
||||
<Border Grid.Column="2" Margin="4,0,0,0" Height="16" Background="Green" CornerRadius="8" VerticalAlignment="Center" IsVisible="{Binding IsGlobal}">
|
||||
<TextBlock Text="GLOBAL" Margin="8,0" FontSize="10" Foreground="White"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<Path Grid.Row="2"
|
||||
Width="64" Height="64"
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
Data="{StaticResource Icons.Empty}"
|
||||
IsVisible="{Binding VisibleActions, Mode=OneWay, Converter={x:Static c:ListConverters.IsNullOrEmpty}}"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
63
src/Views/ExecuteCustomActionCommandPalette.axaml.cs
Normal file
63
src/Views/ExecuteCustomActionCommandPalette.axaml.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class ExecuteCustomActionCommandPalette : UserControl
|
||||
{
|
||||
public ExecuteCustomActionCommandPalette()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override async void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
|
||||
if (DataContext is not ViewModels.ExecuteCustomActionCommandPalette vm)
|
||||
return;
|
||||
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
await vm.ExecAsync();
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Up)
|
||||
{
|
||||
if (ActionListBox.IsKeyboardFocusWithin)
|
||||
{
|
||||
FilterTextBox.Focus(NavigationMethod.Directional);
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (e.Key == Key.Down || e.Key == Key.Tab)
|
||||
{
|
||||
if (FilterTextBox.IsKeyboardFocusWithin)
|
||||
{
|
||||
if (vm.VisibleActions.Count > 0)
|
||||
ActionListBox.Focus(NavigationMethod.Directional);
|
||||
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ActionListBox.IsKeyboardFocusWithin && e.Key == Key.Tab)
|
||||
{
|
||||
FilterTextBox.Focus(NavigationMethod.Directional);
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnItemTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.ExecuteCustomActionCommandPalette vm)
|
||||
{
|
||||
await vm.ExecAsync();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,8 +59,8 @@
|
||||
BorderThickness="1"
|
||||
Margin="8,4,4,8"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
ItemsSource="{Binding Commits}"
|
||||
SelectedItems="{Binding SelectedCommits, Mode=TwoWay}"
|
||||
ItemsSource="{Binding Revisions}"
|
||||
SelectedItems="{Binding SelectedRevisions, Mode=TwoWay}"
|
||||
SelectionMode="Multiple"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto">
|
||||
@@ -79,7 +79,7 @@
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="m:Commit">
|
||||
<DataTemplate DataType="m:FileVersion">
|
||||
<Border BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1" Padding="4">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,96">
|
||||
@@ -93,7 +93,12 @@
|
||||
TextDecorations="Underline"
|
||||
Margin="8,0,0,0"
|
||||
PointerPressed="OnPressCommitSHA"/>
|
||||
<TextBlock Grid.Column="3" Text="{Binding AuthorTimeShortStr}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Right"/>
|
||||
<v:DateTimePresenter Grid.Column="3"
|
||||
Margin="8,0,0,0"
|
||||
ShowDateOnly="True"
|
||||
Timestamp="{Binding AuthorTime}"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
HorizontalAlignment="Right"/>
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="1" Background="Transparent" DataContextChanged="OnCommitSubjectDataContextChanged" PointerMoved="OnCommitSubjectPointerMoved">
|
||||
@@ -110,7 +115,8 @@
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
BorderThickness="1,0,0,0"
|
||||
BorderBrush="{DynamicResource Brush.Border0}"/>
|
||||
BorderBrush="{DynamicResource Brush.Border0}"
|
||||
Focusable="False"/>
|
||||
|
||||
<ContentControl Grid.Column="2" Content="{Binding ViewContent}">
|
||||
<ContentControl.DataTemplates>
|
||||
@@ -195,19 +201,19 @@
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<Grid Grid.Row="0" Margin="4,6" ColumnDefinitions="*,32,*,Auto">
|
||||
<Grid.DataTemplates>
|
||||
<DataTemplate DataType="m:Commit">
|
||||
<DataTemplate DataType="m:FileVersion">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto">
|
||||
<v:Avatar Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/>
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto">
|
||||
<v:Avatar Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Author.Name}" Margin="8,0,0,0"/>
|
||||
<Border Grid.Column="2" Background="{DynamicResource Brush.Accent}" CornerRadius="4" IsVisible="{Binding IsCurrentHead}">
|
||||
<TextBlock Text="HEAD" Margin="4,0" Foreground="#FFDDDDDD"/>
|
||||
</Border>
|
||||
<TextBlock Grid.Column="3" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0" TextDecorations="Underline" Cursor="Hand" PointerPressed="OnPressCommitSHA" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0" TextDecorations="Underline" Cursor="Hand" PointerPressed="OnPressCommitSHA" />
|
||||
<v:DateTimePresenter Grid.Column="3"
|
||||
Margin="8,0,0,0"
|
||||
Timestamp="{Binding AuthorTime}"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="1" Text="{Binding Subject}" VerticalAlignment="Bottom"/>
|
||||
<TextBlock Grid.Row="1" Margin="0,6,0,0" Text="{Binding Subject}" TextTrimming="CharacterEllipsis" VerticalAlignment="Bottom"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</Grid.DataTemplates>
|
||||
|
||||
@@ -16,10 +16,10 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnPressCommitSHA(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender is TextBlock { DataContext: Models.Commit commit } &&
|
||||
if (sender is TextBlock { DataContext: Models.FileVersion ver } &&
|
||||
DataContext is ViewModels.FileHistories vm)
|
||||
{
|
||||
vm.NavigateToCommit(commit);
|
||||
vm.NavigateToCommit(ver);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
@@ -76,12 +76,12 @@ namespace SourceGit.Views
|
||||
|
||||
private void OnCommitSubjectPointerMoved(object sender, PointerEventArgs e)
|
||||
{
|
||||
if (sender is Border { DataContext: Models.Commit commit } border &&
|
||||
if (sender is Border { DataContext: Models.FileVersion ver } border &&
|
||||
DataContext is ViewModels.FileHistories vm)
|
||||
{
|
||||
var tooltip = ToolTip.GetTip(border);
|
||||
if (tooltip == null)
|
||||
ToolTip.SetTip(border, vm.GetCommitFullMessage(commit));
|
||||
ToolTip.SetTip(border, vm.GetCommitFullMessage(ver));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.FileHistoryCommandPalette"
|
||||
x:DataType="vm:FileHistoryCommandPalette">
|
||||
<Grid RowDefinitions="Auto,Auto">
|
||||
<Grid RowDefinitions="Auto,Auto,Auto">
|
||||
<v:RepositoryCommandPaletteTextBox Grid.Row="0"
|
||||
x:Name="FilterTextBox"
|
||||
Height="24"
|
||||
@@ -51,10 +51,16 @@
|
||||
</TextBox.InnerRightContent>
|
||||
</v:RepositoryCommandPaletteTextBox>
|
||||
|
||||
<ListBox Grid.Row="1"
|
||||
<TextBlock Grid.Row="1"
|
||||
Margin="6,12,0,0"
|
||||
Text="{DynamicResource Text.CommandPalette.RevisionFiles}"
|
||||
FontWeight="Bold"
|
||||
Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<ListBox Grid.Row="2"
|
||||
x:Name="FileListBox"
|
||||
MaxHeight="250"
|
||||
Margin="4,8,4,0"
|
||||
MaxHeight="360"
|
||||
Margin="4,8"
|
||||
BorderThickness="0"
|
||||
SelectionMode="Single"
|
||||
Background="Transparent"
|
||||
@@ -88,7 +94,7 @@
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate DataType="x:String">
|
||||
<Grid ColumnDefinitions="Auto,*" Background="Transparent" Tapped="OnItemTapped">
|
||||
<Grid ColumnDefinitions="Auto,*" Background="Transparent" Tapped="OnItemTapped" ToolTip.Tip="{Binding}">
|
||||
<Path Grid.Column="0"
|
||||
Width="12" Height="12"
|
||||
Data="{StaticResource Icons.File}"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:m="using:SourceGit.Models"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.GitFlowStart"
|
||||
x:DataType="vm:GitFlowStart">
|
||||
@@ -38,8 +37,7 @@
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Watermark="{DynamicResource Text.GitFlow.StartPlaceholder}"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Text="{Binding Name, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -87,11 +87,11 @@
|
||||
Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
|
||||
Foreground="DarkOrange"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<TextBlock Grid.Column="3"
|
||||
Margin="4,0"
|
||||
Text="{Binding CommitterTimeShortStr}"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||||
|
||||
<v:DateTimePresenter Grid.Column="3"
|
||||
Margin="4,0"
|
||||
Timestamp="{Binding CommitterTime}"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
|
||||
@@ -157,6 +157,7 @@
|
||||
</v:CommitRefsPresenter>
|
||||
|
||||
<v:CommitSubjectPresenter Grid.Column="3"
|
||||
Height="26"
|
||||
FontFamily="{DynamicResource Fonts.Default}"
|
||||
CodeFontFamily="{DynamicResource Fonts.Monospace}"
|
||||
InlineCodeBackground="{DynamicResource Brush.InlineCode}"
|
||||
@@ -241,8 +242,9 @@
|
||||
<v:CommitTimeTextBlock FontWeight="{Binding IsCurrentHead, Converter={x:Static c:BoolConverters.IsBoldToFontWeight}}"
|
||||
Opacity="{Binding IsMerged, Converter={x:Static c:BoolConverters.IsMergedToOpacity}}"
|
||||
UseAuthorTime="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowAuthorTimeInGraph, Mode=OneWay}"
|
||||
ShowAsDateTime="{Binding Source={x:Static vm:Preferences.Instance}, Path=!DisplayTimeAsPeriodInHistories}"
|
||||
DateTimeFormat="{Binding Source={x:Static vm:Preferences.Instance}, Path=DateTimeFormat}"/>
|
||||
ShowAsDateTime="{Binding Source={x:Static vm:Preferences.Instance}, Path=!DisplayTimeAsPeriodInHistories, Mode=OneWay}"
|
||||
DateTimeFormat="{Binding Source={x:Static vm:Preferences.Instance}, Path=DateTimeFormat, Mode=OneWay}"
|
||||
Use24Hours="{Binding Source={x:Static vm:Preferences.Instance}, Path=Use24Hours, Mode=OneWay}"/>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
@@ -277,7 +279,8 @@
|
||||
MinWidth="1" MinHeight="1"
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Background="{DynamicResource Brush.Window}"
|
||||
BorderBrush="{DynamicResource Brush.Border0}"/>
|
||||
BorderBrush="{DynamicResource Brush.Border0}"
|
||||
Focusable="False"/>
|
||||
|
||||
<Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3">
|
||||
<Grid IsVisible="{Binding DetailContext, Converter={x:Static ObjectConverters.IsNull}}">
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Classes="bold" Text="{OnPlatform Ctrl+Shift+H, macOS=⌘+⇧+H}"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.GoHome}" />
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Classes="bold" Text="{OnPlatform Ctrl+F, macOS=⌘+F}"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Classes="bold" Text="{OnPlatform Ctrl+Shift+F, macOS=⌘+⇧+F}"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.OpenSearchCommits}" />
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Classes="bold" Text="{OnPlatform Ctrl+1, macOS=⌘+1}"/>
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
Classes="bold"
|
||||
Text="{DynamicResource Text.Init}"/>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<Grid Margin="0,16,8,0" ColumnDefinitions="100,*">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="32"/>
|
||||
<RowDefinition Height="Auto" MinHeight="32"/>
|
||||
<RowDefinition Height="Auto" MinHeight="32"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
@@ -29,9 +30,17 @@
|
||||
Margin="0,0,8,0"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1"
|
||||
Text="{Binding TargetPath}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="1"
|
||||
Foreground="{DynamicResource Brush.FG2}"
|
||||
Text="{Binding Reason}"
|
||||
TextWrapping="Wrap">
|
||||
<Run Text="{DynamicResource Text.Init.ErrorMessageTip}"/>
|
||||
<Run Text="{Binding Reason, Mode=OneWay}" />
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="1"
|
||||
Margin="0,8,0,0"
|
||||
Text="{DynamicResource Text.Init.CommandTip}"
|
||||
TextWrapping="Wrap"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.InitGitFlow"
|
||||
x:DataType="vm:InitGitFlow">
|
||||
@@ -27,8 +26,7 @@
|
||||
Height="26"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
Text="{Binding Master, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Text="{Binding Master, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
|
||||
@@ -155,6 +155,7 @@
|
||||
</Button>
|
||||
|
||||
<v:CommitSubjectPresenter Grid.Column="1"
|
||||
Height="28"
|
||||
Margin="0,0,4,0"
|
||||
FontFamily="{DynamicResource Fonts.Default}"
|
||||
CodeFontFamily="{DynamicResource Fonts.Monospace}"
|
||||
@@ -164,8 +165,8 @@
|
||||
Subject="{Binding Subject}"
|
||||
IssueTrackers="{Binding $parent[v:InteractiveRebase].((vm:InteractiveRebase)DataContext).IssueTrackers}"
|
||||
FontWeight="Normal"
|
||||
Opacity="{Binding IsFullMessageUsed, Converter={x:Static c:BoolConverters.IsMergedToOpacity}}"
|
||||
ShowStrikethrough="{Binding Action, Mode=OneWay, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:InteractiveRebaseAction.Drop}}"/>
|
||||
Opacity="{Binding Action, Mode=OneWay, Converter={x:Static c:InteractiveRebaseActionConverters.ToOpacity}}"
|
||||
ShowStrikethrough="{Binding Action, Mode=OneWay, Converter={x:Static c:InteractiveRebaseActionConverters.IsDrop}}"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Author Avatar -->
|
||||
@@ -173,27 +174,29 @@
|
||||
Width="16" Height="16"
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
User="{Binding Commit.Author}"
|
||||
Opacity="{Binding IsFullMessageUsed, Converter={x:Static c:BoolConverters.IsMergedToOpacity}}"/>
|
||||
User="{Binding Commit.Author}"/>
|
||||
|
||||
<!-- Author Name -->
|
||||
<Border Grid.Column="5" ClipToBounds="True">
|
||||
<TextBlock Margin="6,0,12,0"
|
||||
Text="{Binding Commit.Author.Name}"
|
||||
Opacity="{Binding IsFullMessageUsed, Converter={x:Static c:BoolConverters.IsMergedToOpacity}}"/>
|
||||
Text="{Binding Commit.Author.Name}"
|
||||
Opacity="{Binding Action, Mode=OneWay, Converter={x:Static c:InteractiveRebaseActionConverters.ToOpacity}}"
|
||||
Classes.dropped="{Binding Action, Mode=OneWay, Converter={x:Static c:InteractiveRebaseActionConverters.IsDrop}}"/>
|
||||
</Border>
|
||||
|
||||
<!-- Commit SHA -->
|
||||
<Border Grid.Column="6" ClipToBounds="True">
|
||||
<TextBlock Text="{Binding Commit.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
|
||||
Opacity="{Binding IsFullMessageUsed, Converter={x:Static c:BoolConverters.IsMergedToOpacity}}"/>
|
||||
Opacity="{Binding Action, Mode=OneWay, Converter={x:Static c:InteractiveRebaseActionConverters.ToOpacity}}"
|
||||
Classes.dropped="{Binding Action, Mode=OneWay, Converter={x:Static c:InteractiveRebaseActionConverters.IsDrop}}"/>
|
||||
</Border>
|
||||
|
||||
<!-- Commit Time -->
|
||||
<Border Grid.Column="7">
|
||||
<TextBlock Margin="16,0,8,0"
|
||||
Text="{Binding Commit.CommitterTimeStr}"
|
||||
Opacity="{Binding IsFullMessageUsed, Converter={x:Static c:BoolConverters.IsMergedToOpacity}}"/>
|
||||
<v:DateTimePresenter Margin="16,0,8,0"
|
||||
Timestamp="{Binding Commit.CommitterTime}"
|
||||
Opacity="{Binding Action, Mode=OneWay, Converter={x:Static c:InteractiveRebaseActionConverters.ToOpacity}}"
|
||||
Classes.dropped="{Binding Action, Mode=OneWay, Converter={x:Static c:InteractiveRebaseActionConverters.IsDrop}}"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
@@ -207,7 +210,8 @@
|
||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Background="Transparent"
|
||||
BorderThickness="0,1,0,0"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"/>
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
Focusable="False"/>
|
||||
|
||||
<ContentControl Grid.Row="2">
|
||||
<ContentControl.Content>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:vm="using:SourceGit.ViewModels"
|
||||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.LFSTrackCustomPattern"
|
||||
x:DataType="vm:LFSTrackCustomPattern">
|
||||
@@ -26,8 +25,7 @@
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding Pattern, Mode=TwoWay}"
|
||||
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||
Text="{Binding Pattern, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="1" Grid.Column="1"
|
||||
Content="{DynamicResource Text.GitLFS.AddTrackPattern.IsFilename}"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user