mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-21 12:15:00 +00:00
Merge branch 'release/v2025.08'
This commit is contained in:
commit
18d3b9560b
63 changed files with 781 additions and 495 deletions
17
.github/workflows/build.yml
vendored
17
.github/workflows/build.yml
vendored
|
@ -19,14 +19,25 @@ jobs:
|
|||
os: macos-latest
|
||||
runtime: osx-arm64
|
||||
- name : Linux
|
||||
os: ubuntu-20.04
|
||||
os: ubuntu-latest
|
||||
runtime: linux-x64
|
||||
container: ubuntu:20.04
|
||||
- name : Linux (arm64)
|
||||
os: ubuntu-20.04
|
||||
os: ubuntu-latest
|
||||
runtime: linux-arm64
|
||||
container: ubuntu:20.04
|
||||
name: Build ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container || '' }}
|
||||
steps:
|
||||
- name: Install common CLI tools
|
||||
if: ${{ startsWith(matrix.runtime, 'linux-') }}
|
||||
run: |
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime
|
||||
apt-get update
|
||||
apt-get install -y sudo
|
||||
sudo apt-get install -y curl wget git unzip zip libicu66 tzdata clang
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup .NET
|
||||
|
@ -47,7 +58,7 @@ jobs:
|
|||
if: ${{ matrix.runtime == 'linux-arm64' }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install clang llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64
|
||||
sudo apt-get install -y llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64
|
||||
- name: Build
|
||||
run: dotnet build -c Release
|
||||
- name: Publish
|
||||
|
|
14
.github/workflows/package.yml
vendored
14
.github/workflows/package.yml
vendored
|
@ -9,10 +9,10 @@ on:
|
|||
jobs:
|
||||
windows:
|
||||
name: Package Windows
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: windows-2019
|
||||
strategy:
|
||||
matrix:
|
||||
runtime: [win-x64, win-arm64]
|
||||
runtime: [ win-x64, win-arm64 ]
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v4
|
||||
|
@ -22,6 +22,7 @@ jobs:
|
|||
name: sourcegit.${{ matrix.runtime }}
|
||||
path: build/SourceGit
|
||||
- name: Package
|
||||
shell: bash
|
||||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
RUNTIME: ${{ matrix.runtime }}
|
||||
|
@ -69,6 +70,7 @@ jobs:
|
|||
linux:
|
||||
name: Package Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ubuntu:20.04
|
||||
strategy:
|
||||
matrix:
|
||||
runtime: [linux-x64, linux-arm64]
|
||||
|
@ -77,9 +79,10 @@ jobs:
|
|||
uses: actions/checkout@v4
|
||||
- name: Download package dependencies
|
||||
run: |
|
||||
sudo add-apt-repository universe
|
||||
sudo apt-get update
|
||||
sudo apt-get install desktop-file-utils rpm libfuse2
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
ln -fs /usr/share/zoneinfo/Etc/UTC /etc/localtime
|
||||
apt-get update
|
||||
apt-get install -y curl wget git dpkg-dev fakeroot tzdata zip unzip desktop-file-utils rpm libfuse2 file build-essential binutils
|
||||
- name: Download build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
|
@ -89,6 +92,7 @@ jobs:
|
|||
env:
|
||||
VERSION: ${{ inputs.version }}
|
||||
RUNTIME: ${{ matrix.runtime }}
|
||||
APPIMAGE_EXTRACT_AND_RUN: 1
|
||||
run: |
|
||||
mkdir build/SourceGit
|
||||
tar -xf "build/sourcegit.${{ matrix.runtime }}.tar" -C build/SourceGit
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
## Translation Status
|
||||
|
||||
[](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md)
|
||||
[](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md) [](TRANSLATION.md)
|
||||
|
||||
> [!NOTE]
|
||||
> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md)
|
||||
|
|
|
@ -60,6 +60,8 @@ EndProject
|
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DEBIAN", "DEBIAN", "{F101849D-BDB7-40D4-A516-751150C3CCFC}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
build\resources\deb\DEBIAN\control = build\resources\deb\DEBIAN\control
|
||||
build\resources\deb\DEBIAN\preinst = build\resources\deb\DEBIAN\preinst
|
||||
build\resources\deb\DEBIAN\prerm = build\resources\deb\DEBIAN\prerm
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rpm", "rpm", "{9BA0B044-0CC9-46F8-B551-204F149BF45D}"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
### de_DE.axaml: 99.21%
|
||||
### de_DE.axaml: 99.08%
|
||||
|
||||
|
||||
<details>
|
||||
|
@ -9,21 +9,22 @@
|
|||
- Text.Diff.First
|
||||
- Text.Diff.Last
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.Preferences.Appearance.EditorTabWidth
|
||||
- Text.StashCM.SaveAsPatch
|
||||
|
||||
</details>
|
||||
|
||||
### es_ES.axaml: 99.87%
|
||||
### es_ES.axaml: 100.00%
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Missing Keys</summary>
|
||||
|
||||
- Text.StashCM.SaveAsPatch
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
### fr_FR.axaml: 91.80%
|
||||
### fr_FR.axaml: 91.68%
|
||||
|
||||
|
||||
<details>
|
||||
|
@ -56,6 +57,7 @@
|
|||
- Text.MergeMultiple.Strategy
|
||||
- Text.MergeMultiple.Targets
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.Preferences.Appearance.EditorTabWidth
|
||||
- Text.Preferences.Appearance.FontSize
|
||||
- Text.Preferences.Appearance.FontSize.Default
|
||||
- Text.Preferences.Appearance.FontSize.Editor
|
||||
|
@ -94,17 +96,17 @@
|
|||
|
||||
</details>
|
||||
|
||||
### it_IT.axaml: 100.00%
|
||||
### it_IT.axaml: 99.87%
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Missing Keys</summary>
|
||||
|
||||
|
||||
- Text.Preferences.Appearance.EditorTabWidth
|
||||
|
||||
</details>
|
||||
|
||||
### pt_BR.axaml: 91.53%
|
||||
### pt_BR.axaml: 91.41%
|
||||
|
||||
|
||||
<details>
|
||||
|
@ -148,6 +150,7 @@
|
|||
- Text.MergeMultiple.Strategy
|
||||
- Text.MergeMultiple.Targets
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.Preferences.Appearance.EditorTabWidth
|
||||
- Text.Preferences.General.DateFormat
|
||||
- Text.Preferences.General.ShowChildren
|
||||
- Text.Preferences.Git.SSLVerify
|
||||
|
@ -177,19 +180,13 @@
|
|||
|
||||
</details>
|
||||
|
||||
### ru_RU.axaml: 99.07%
|
||||
### ru_RU.axaml: 100.00%
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Missing Keys</summary>
|
||||
|
||||
- Text.BranchCM.CustomAction
|
||||
- Text.BranchUpstreamInvalid
|
||||
- Text.Configure.CustomAction.Scope.Branch
|
||||
- Text.Diff.First
|
||||
- Text.Diff.Last
|
||||
- Text.Preferences.AI.Streaming
|
||||
- Text.StashCM.SaveAsPatch
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2025.07
|
||||
2025.08
|
32
build/resources/deb/DEBIAN/preinst
Executable file
32
build/resources/deb/DEBIAN/preinst
Executable file
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
# Check if SourceGit is running and stop it
|
||||
if pgrep -f '/opt/sourcegit/sourcegit' > /dev/null; then
|
||||
echo "Stopping running SourceGit instance..."
|
||||
pkill -f '/opt/sourcegit/sourcegit' || true
|
||||
# Give the process a moment to terminate
|
||||
sleep 1
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
35
build/resources/deb/DEBIAN/prerm
Executable file
35
build/resources/deb/DEBIAN/prerm
Executable file
|
@ -0,0 +1,35 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
if pgrep -f '/opt/sourcegit/sourcegit' > /dev/null; then
|
||||
echo "Stopping running SourceGit instance..."
|
||||
pkill -f '/opt/sourcegit/sourcegit' || true
|
||||
# Give the process a moment to terminate
|
||||
sleep 1
|
||||
fi
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -9,4 +9,8 @@ cd build
|
|||
|
||||
rm -rf SourceGit/*.pdb
|
||||
|
||||
zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit
|
||||
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "win32" ]]; then
|
||||
powershell -Command "Compress-Archive -Path SourceGit\\* -DestinationPath \"sourcegit_$VERSION.$RUNTIME.zip\" -Force"
|
||||
else
|
||||
zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit
|
||||
fi
|
||||
|
|
|
@ -445,10 +445,14 @@ namespace SourceGit
|
|||
|
||||
var file = args[1];
|
||||
if (!File.Exists(file))
|
||||
{
|
||||
desktop.Shutdown(-1);
|
||||
else
|
||||
desktop.MainWindow = new Views.StandaloneCommitMessageEditor(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
var editor = new Views.StandaloneCommitMessageEditor();
|
||||
editor.SetFile(file);
|
||||
desktop.MainWindow = editor;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -461,7 +465,9 @@ namespace SourceGit
|
|||
var args = desktop.Args;
|
||||
if (args?.Length > 0)
|
||||
{
|
||||
desktop.MainWindow = new Views.Askpass(args[0]);
|
||||
var askpass = new Views.Askpass();
|
||||
askpass.TxtDescription.Text = args[0];
|
||||
desktop.MainWindow = askpass;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,18 @@ namespace SourceGit.Commands
|
|||
return;
|
||||
}
|
||||
|
||||
if (line.StartsWith("deleted file mode ", StringComparison.Ordinal))
|
||||
{
|
||||
_result.OldMode = line.Substring(18);
|
||||
return;
|
||||
}
|
||||
|
||||
if (line.StartsWith("new file mode ", StringComparison.Ordinal))
|
||||
{
|
||||
_result.NewMode = line.Substring(14);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_result.IsBinary)
|
||||
return;
|
||||
|
||||
|
|
17
src/Commands/IsCommitSHA.cs
Normal file
17
src/Commands/IsCommitSHA.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
namespace SourceGit.Commands
|
||||
{
|
||||
public class IsCommitSHA : Command
|
||||
{
|
||||
public IsCommitSHA(string repo, string hash)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Args = $"cat-file -t {hash}";
|
||||
}
|
||||
|
||||
public bool Result()
|
||||
{
|
||||
var rs = ReadToEnd();
|
||||
return rs.IsSuccess && rs.StdOut.Trim().Equals("commit");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,10 +11,11 @@ namespace SourceGit.Commands
|
|||
Context = repo;
|
||||
TraitErrorAsOutput = true;
|
||||
SSHKey = new Config(repo).Get($"remote.{remote}.sshkey");
|
||||
Args = "pull --verbose --progress --tags ";
|
||||
Args = "pull --verbose --progress ";
|
||||
|
||||
if (useRebase)
|
||||
Args += "--rebase ";
|
||||
Args += "--rebase=true ";
|
||||
|
||||
if (noTags)
|
||||
Args += "--no-tags ";
|
||||
|
||||
|
|
|
@ -3,18 +3,18 @@ using System.Collections.Generic;
|
|||
|
||||
namespace SourceGit.Commands
|
||||
{
|
||||
public class QueryCommitsWithFullMessage : Command
|
||||
public class QueryCommitsForInteractiveRebase : Command
|
||||
{
|
||||
public QueryCommitsWithFullMessage(string repo, string args)
|
||||
public QueryCommitsForInteractiveRebase(string repo, string on)
|
||||
{
|
||||
_boundary = $"----- BOUNDARY OF COMMIT {Guid.NewGuid()} -----";
|
||||
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {args}";
|
||||
Args = $"log --date-order --no-show-signature --decorate=full --pretty=format:\"%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%B%n{_boundary}\" {on}..HEAD";
|
||||
}
|
||||
|
||||
public List<Models.CommitWithMessage> Result()
|
||||
public List<Models.InteractiveCommit> Result()
|
||||
{
|
||||
var rs = ReadToEnd();
|
||||
if (!rs.IsSuccess)
|
||||
|
@ -29,7 +29,7 @@ namespace SourceGit.Commands
|
|||
switch (nextPartIdx)
|
||||
{
|
||||
case 0:
|
||||
_current = new Models.CommitWithMessage();
|
||||
_current = new Models.InteractiveCommit();
|
||||
_current.Commit.SHA = line;
|
||||
_commits.Add(_current);
|
||||
break;
|
||||
|
@ -52,7 +52,7 @@ namespace SourceGit.Commands
|
|||
_current.Commit.CommitterTime = ulong.Parse(line);
|
||||
break;
|
||||
default:
|
||||
var boundary = rs.StdOut.IndexOf(_boundary, end + 1);
|
||||
var boundary = rs.StdOut.IndexOf(_boundary, end + 1, StringComparison.Ordinal);
|
||||
if (boundary > end)
|
||||
{
|
||||
_current.Message = rs.StdOut.Substring(start, boundary - start - 1);
|
||||
|
@ -88,8 +88,8 @@ namespace SourceGit.Commands
|
|||
_current.Commit.Parents.AddRange(data.Split(separator: ' ', options: StringSplitOptions.RemoveEmptyEntries));
|
||||
}
|
||||
|
||||
private List<Models.CommitWithMessage> _commits = new List<Models.CommitWithMessage>();
|
||||
private Models.CommitWithMessage _current = null;
|
||||
private List<Models.InteractiveCommit> _commits = [];
|
||||
private Models.InteractiveCommit _current = null;
|
||||
private string _boundary = "";
|
||||
}
|
||||
}
|
21
src/Commands/QueryRevisionByRefName.cs
Normal file
21
src/Commands/QueryRevisionByRefName.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
namespace SourceGit.Commands
|
||||
{
|
||||
public class QueryRevisionByRefName : Command
|
||||
{
|
||||
public QueryRevisionByRefName(string repo, string refname)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
Args = $"rev-parse {refname}";
|
||||
}
|
||||
|
||||
public string Result()
|
||||
{
|
||||
var rs = ReadToEnd();
|
||||
if (rs.IsSuccess && !string.IsNullOrEmpty(rs.StdOut))
|
||||
return rs.StdOut.Trim();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -112,9 +112,9 @@ namespace SourceGit.Models
|
|||
}
|
||||
}
|
||||
|
||||
public class CommitWithMessage
|
||||
public class CommitFullMessage
|
||||
{
|
||||
public Commit Commit { get; set; } = new Commit();
|
||||
public string Message { get; set; } = "";
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public List<Hyperlink> Links { get; set; } = [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -681,6 +681,18 @@ namespace SourceGit.Models
|
|||
public TextDiff TextDiff { get; set; } = null;
|
||||
public LFSDiff LFSDiff { get; set; } = null;
|
||||
|
||||
public string FileModeChange => string.IsNullOrEmpty(OldMode) ? string.Empty : $"{OldMode} → {NewMode}";
|
||||
public string FileModeChange
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(OldMode) && string.IsNullOrEmpty(NewMode))
|
||||
return string.Empty;
|
||||
|
||||
var oldDisplay = string.IsNullOrEmpty(OldMode) ? "0" : OldMode;
|
||||
var newDisplay = string.IsNullOrEmpty(NewMode) ? "0" : NewMode;
|
||||
|
||||
return $"{oldDisplay} → {newDisplay}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,12 @@ namespace SourceGit.Models
|
|||
Drop,
|
||||
}
|
||||
|
||||
public class InteractiveCommit
|
||||
{
|
||||
public Commit Commit { get; set; } = new Commit();
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class InteractiveRebaseJob
|
||||
{
|
||||
public string SHA { get; set; } = string.Empty;
|
||||
|
|
|
@ -29,6 +29,6 @@ namespace SourceGit.Models
|
|||
public class RevisionSubmodule
|
||||
{
|
||||
public Commit Commit { get; set; } = null;
|
||||
public string FullMessage { get; set; } = string.Empty;
|
||||
public CommitFullMessage FullMessage { get; set; } = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -464,6 +464,7 @@
|
|||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Enable Streaming</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APPEARANCE</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Default Font</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Editor Tab Width</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Font Size</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Default</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Editor</x:String>
|
||||
|
|
|
@ -24,17 +24,17 @@
|
|||
<x:String x:Key="Text.AIAssistant.Regen" xml:space="preserve">RE-GENERAR</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Usar OpenAI para generar mensaje de commit</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">APLICAR CÓMO MENSAJE DE COMMIT</x:String>
|
||||
<x:String x:Key="Text.Apply" xml:space="preserve">Aplicar Patch</x:String>
|
||||
<x:String x:Key="Text.Apply" xml:space="preserve">Aplicar Parche</x:String>
|
||||
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Error</x:String>
|
||||
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Genera errores y se niega a aplicar el patch</x:String>
|
||||
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Genera errores y se niega a aplicar el parche</x:String>
|
||||
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Error Todo</x:String>
|
||||
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similar a 'error', pero muestra más</x:String>
|
||||
<x:String x:Key="Text.Apply.File" xml:space="preserve">Archivo Patch:</x:String>
|
||||
<x:String x:Key="Text.Apply.File" xml:space="preserve">Archivo del Parche:</x:String>
|
||||
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Seleccionar archivo .patch para aplicar</x:String>
|
||||
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorar cambios de espacios en blanco</x:String>
|
||||
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Sin Advertencia</x:String>
|
||||
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Desactiva la advertencia de espacios en blanco al final</x:String>
|
||||
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Aplicar Patch</x:String>
|
||||
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Aplicar Parche</x:String>
|
||||
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Advertencia</x:String>
|
||||
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Genera advertencias para algunos de estos errores, pero aplica</x:String>
|
||||
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espacios en Blanco:</x:String>
|
||||
|
@ -126,7 +126,7 @@
|
|||
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ hasta Aquí</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Revertir Commit</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Reescribir</x:String>
|
||||
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Guardar como Patch...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Guardar como Parche...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash en Parent</x:String>
|
||||
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Squash Commits Hijos hasta Aquí</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CAMBIOS</x:String>
|
||||
|
@ -259,7 +259,7 @@
|
|||
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Siguiente Diferencia</x:String>
|
||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">SIN CAMBIOS O SOLO CAMBIOS DE EOL</x:String>
|
||||
<x:String x:Key="Text.Diff.Prev" xml:space="preserve">Diferencia Anterior</x:String>
|
||||
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">Guardar como Patch</x:String>
|
||||
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">Guardar como Parche</x:String>
|
||||
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Mostrar símbolos ocultos</x:String>
|
||||
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Diferencia Lado a Lado</x:String>
|
||||
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SUBMÓDULO</x:String>
|
||||
|
@ -300,7 +300,7 @@
|
|||
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">Descartar Cambios en Línea(s) Seleccionada(s)</x:String>
|
||||
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Abrir Herramienta de Merge Externa</x:String>
|
||||
<x:String x:Key="Text.FileCM.ResolveUsing" xml:space="preserve">Resolver usando ${0}$</x:String>
|
||||
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Guardar Como Patch...</x:String>
|
||||
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Guardar como Parche...</x:String>
|
||||
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">Stage</x:String>
|
||||
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">Stage {0} archivos</x:String>
|
||||
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Stage Cambios en Línea(s) Seleccionada(s)</x:String>
|
||||
|
@ -468,6 +468,7 @@
|
|||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Activar Transmisión</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APARIENCIA</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Fuente por defecto</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Ancho de la Pestaña del Editor</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Tamaño de fuente</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Por defecto</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Editor</x:String>
|
||||
|
@ -638,7 +639,7 @@
|
|||
<x:String x:Key="Text.Running" xml:space="preserve">Ejecutando. Por favor espera...</x:String>
|
||||
<x:String x:Key="Text.Save" xml:space="preserve">GUARDAR</x:String>
|
||||
<x:String x:Key="Text.SaveAs" xml:space="preserve">Guardar Como...</x:String>
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">¡El patch se ha guardado exitosamente!</x:String>
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">¡El parche se ha guardado exitosamente!</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">Escanear Repositorios</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.RootDir" xml:space="preserve">Directorio Raíz:</x:String>
|
||||
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">Buscar Actualizaciones...</x:String>
|
||||
|
@ -672,6 +673,7 @@
|
|||
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Aplicar</x:String>
|
||||
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Eliminar</x:String>
|
||||
<x:String x:Key="Text.StashCM.Pop" xml:space="preserve">Pop</x:String>
|
||||
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Guardar como Parche...</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Eliminar Stash</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Eliminar:</x:String>
|
||||
<x:String x:Key="Text.Stashes" xml:space="preserve">Stashes</x:String>
|
||||
|
|
|
@ -20,21 +20,21 @@
|
|||
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Имя целевого каталога по умолчанию. (необязательно)</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Отслеживание ветки:</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Отслеживание внешней ветки</x:String>
|
||||
<x:String x:Key="Text.AIAssistant" xml:space="preserve">OpenAI Ассистент</x:String>
|
||||
<x:String x:Key="Text.AIAssistant" xml:space="preserve">Помощник OpenAI</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Regen" xml:space="preserve">ПЕРЕСОЗДАТЬ</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Использовать OpenAI для создания сообщения о ревизии</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">ПРИМЕНИТЬ КАК СООБЩЕНИЕ РЕВИЗИИ</x:String>
|
||||
<x:String x:Key="Text.Apply" xml:space="preserve">Исправить </x:String>
|
||||
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Ошибка</x:String>
|
||||
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Выдает ошибки и отказывается применять исправление</x:String>
|
||||
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Выдает ошибки и отказывается применять заплатку</x:String>
|
||||
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Все ошибки</x:String>
|
||||
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Аналогично «ошибке», но показывает больше</x:String>
|
||||
<x:String x:Key="Text.Apply.File" xml:space="preserve">Файл исправлений:</x:String>
|
||||
<x:String x:Key="Text.Apply.File" xml:space="preserve">Файл заплатки:</x:String>
|
||||
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Выберите файл .patch для применения</x:String>
|
||||
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Игнорировать изменения пробелов</x:String>
|
||||
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Нет предупреждений</x:String>
|
||||
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Отключить предупреждения о пробелах в конце</x:String>
|
||||
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Применить исправление</x:String>
|
||||
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Применить заплатку</x:String>
|
||||
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Предупреждать</x:String>
|
||||
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Выдавать предупреждения о нескольких таких ошибках, но применять</x:String>
|
||||
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Пробел:</x:String>
|
||||
|
@ -58,6 +58,7 @@
|
|||
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Сравнить с ГОЛОВОЙ (HEAD)</x:String>
|
||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Сравнить с рабочим каталогом</x:String>
|
||||
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Копировать имя ветки</x:String>
|
||||
<x:String x:Key="Text.BranchCM.CustomAction" xml:space="preserve">Изменить действие</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Удалить ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Удалить выбранные {0} ветки</x:String>
|
||||
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Отклонить все изменения.</x:String>
|
||||
|
@ -73,6 +74,7 @@
|
|||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Переименовать ${0}$...</x:String>
|
||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Отслеживать ветку...</x:String>
|
||||
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Сравнение веток</x:String>
|
||||
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Недопустимая основная ветка!</x:String>
|
||||
<x:String x:Key="Text.Bytes" xml:space="preserve">Байты</x:String>
|
||||
<x:String x:Key="Text.Cancel" xml:space="preserve">ОТМЕНА</x:String>
|
||||
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Сбросить эту ревизию</x:String>
|
||||
|
@ -105,7 +107,7 @@
|
|||
<x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Локальное имя:</x:String>
|
||||
<x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Имя репозитория. (необязательно).</x:String>
|
||||
<x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Родительский каталог:</x:String>
|
||||
<x:String x:Key="Text.Clone.RecurseSubmodules" xml:space="preserve">Инициализировать и обновить подмодуль</x:String>
|
||||
<x:String x:Key="Text.Clone.RecurseSubmodules" xml:space="preserve">Создать и обновить подмодуль</x:String>
|
||||
<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>
|
||||
|
@ -119,7 +121,7 @@
|
|||
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Пользовательское действие</x:String>
|
||||
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Интерактивное перемещение (rebase -i) ${0}$ сюда</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Влить в ${0}$</x:String>
|
||||
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Влить ветки...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.MergeMultiple" xml:space="preserve">Влить ...</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Переместить ${0}$ сюда</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Сбросить ${0}$ сюда</x:String>
|
||||
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Отменить ревизию</x:String>
|
||||
|
@ -137,7 +139,7 @@
|
|||
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">АВТОР</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">ИЗМЕНЁННЫЙ</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Children" xml:space="preserve">ДОЧЕРНИЙ</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">РЕВИЗОР(ИСПОЛНИТЕЛЬ)</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">РЕВИЗОР (ИСПОЛНИТЕЛЬ)</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Найти все ветки с этой ревизией</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">ВЕТКИ С ЭТОЙ РЕВИЗИЕЙ</x:String>
|
||||
<x:String x:Key="Text.CommitDetail.Info.GotoChangesPage" xml:space="preserve">Отображаются только первые 100 изменений. Смотрите все изменения на вкладке ИЗМЕНЕНИЯ.</x:String>
|
||||
|
@ -158,6 +160,7 @@
|
|||
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Исполняемый файл:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Имя:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Диапазон:</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Branch" xml:space="preserve">Ветка</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Ревизия</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Репозиторий</x:String>
|
||||
<x:String x:Key="Text.Configure.CustomAction.WaitForExit" xml:space="preserve">Ждать для выполения выхода</x:String>
|
||||
|
@ -250,13 +253,15 @@
|
|||
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">СТАРЫЙ</x:String>
|
||||
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">Копировать</x:String>
|
||||
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">Режим файла изменён</x:String>
|
||||
<x:String x:Key="Text.Diff.First" xml:space="preserve">Первое различие</x:String>
|
||||
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">Игнорировать изменение пробелов</x:String>
|
||||
<x:String x:Key="Text.Diff.Last" xml:space="preserve">Последнее различие</x:String>
|
||||
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Показывать скрытые символы</x:String>
|
||||
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">ИЗМЕНЕНИЕ ОБЪЕКТА LFS</x:String>
|
||||
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Следующее различие</x:String>
|
||||
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">НИКАКИХ ИЗМЕНЕНИЙ ИЛИ МЕНЯЕТСЯ ТОЛЬКО EOL</x:String>
|
||||
<x:String x:Key="Text.Diff.Prev" xml:space="preserve">Предыдущее различие</x:String>
|
||||
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">Сохранить как исправление</x:String>
|
||||
<x:String x:Key="Text.Diff.SaveAsPatch" xml:space="preserve">Сохранить как заплатку</x:String>
|
||||
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Различие бок о бок</x:String>
|
||||
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">ПОДМОДУЛЬ</x:String>
|
||||
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">НОВЫЙ</x:String>
|
||||
|
@ -286,7 +291,7 @@
|
|||
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Быстрая перемотка вперёд (без проверки)</x:String>
|
||||
<x:String x:Key="Text.Fetch" xml:space="preserve">Извлечь</x:String>
|
||||
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Извлечь все внешние репозитории</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Разрешить опцию '--force'</x:String>
|
||||
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Разрешить опцию (--force)</x:String>
|
||||
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">Извлечь без меток</x:String>
|
||||
<x:String x:Key="Text.Fetch.Remote" xml:space="preserve">Внешний репозиторий:</x:String>
|
||||
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">Извлечь внешние изменения</x:String>
|
||||
|
@ -296,7 +301,7 @@
|
|||
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">Отменить изменения в выбранной(ых) строке(ах)</x:String>
|
||||
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Открыть расширенный инструмент слияния</x:String>
|
||||
<x:String x:Key="Text.FileCM.ResolveUsing" xml:space="preserve">Взять версию ${0}$</x:String>
|
||||
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Сохранить как patch-файл...</x:String>
|
||||
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Сохранить как файл заплатки...</x:String>
|
||||
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">Подготовить</x:String>
|
||||
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">Подготовленные {0} файлы</x:String>
|
||||
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Подготовленные изменения в выбранной(ых) строке(ах)</x:String>
|
||||
|
@ -320,7 +325,7 @@
|
|||
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Цель:</x:String>
|
||||
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Исправление:</x:String>
|
||||
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Префикс исправлений:</x:String>
|
||||
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Инициализировать Git-поток</x:String>
|
||||
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Создать Git-поток</x:String>
|
||||
<x:String x:Key="Text.GitFlow.KeepBranchAfterFinish" xml:space="preserve">Держать ветку</x:String>
|
||||
<x:String x:Key="Text.GitFlow.ProductionBranch" xml:space="preserve">Производственная ветка:</x:String>
|
||||
<x:String x:Key="Text.GitFlow.Release" xml:space="preserve">Выпуск:</x:String>
|
||||
|
@ -403,7 +408,7 @@
|
|||
<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.Hunk.Discard" xml:space="preserve">Отклонить</x:String>
|
||||
<x:String x:Key="Text.Init" xml:space="preserve">Инициализировать репозиторий</x:String>
|
||||
<x:String x:Key="Text.Init" 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>
|
||||
|
@ -460,10 +465,12 @@
|
|||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Модель</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Имя:</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Сервер</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Разрешить потоковую передачу</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">ВИД</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Шрифт по умолчанию</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Размер шрифта</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">По умолчанию</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Редактировать ширину вкладки</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Редактор</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.MonospaceFont" xml:space="preserve">Моноширный шрифт</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">В текстовом редакторе используется только моноширный шрифт</x:String>
|
||||
|
@ -488,7 +495,7 @@
|
|||
<x:String x:Key="Text.Preferences.Git.DefaultCloneDir" xml:space="preserve">Каталог клонирования по умолчанию</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.Email" xml:space="preserve">Электроная почта пользователя</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.Email.Placeholder" xml:space="preserve">Общая электроная почта пользователя git</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.EnablePruneOnFetch" xml:space="preserve">Разрешить '--prune' при скачивании</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.EnablePruneOnFetch" xml:space="preserve">Разрешить (--prune) при скачивании</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.Path" xml:space="preserve">Путь установки</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.SSLVerify" xml:space="preserve">Разрешить верификацию HTTP SSL</x:String>
|
||||
<x:String x:Key="Text.Preferences.Git.User" xml:space="preserve">Имя пользователя</x:String>
|
||||
|
@ -555,7 +562,7 @@
|
|||
<x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">Открыть в браузере</x:String>
|
||||
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Удалить</x:String>
|
||||
<x:String x:Key="Text.RemoveWorktree" xml:space="preserve">Подтвердить удаление рабочего каталога</x:String>
|
||||
<x:String x:Key="Text.RemoveWorktree.Force" xml:space="preserve">Включить опцию --force</x:String>
|
||||
<x:String x:Key="Text.RemoveWorktree.Force" xml:space="preserve">Включить опцию (--force)</x:String>
|
||||
<x:String x:Key="Text.RemoveWorktree.Target" xml:space="preserve">Цель:</x:String>
|
||||
<x:String x:Key="Text.RenameBranch" xml:space="preserve">Переименовать ветку</x:String>
|
||||
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">Новое имя:</x:String>
|
||||
|
@ -578,7 +585,7 @@
|
|||
<x:String x:Key="Text.Repository.FilterCommits.Exclude" xml:space="preserve">Скрыть в графе ревизии</x:String>
|
||||
<x:String x:Key="Text.Repository.FilterCommits.Include" xml:space="preserve">Фильтр в графе ревизии</x:String>
|
||||
<x:String x:Key="Text.Repository.FilterCommits.Prefix" xml:space="preserve">ОТФИЛЬТРОВАНО:</x:String>
|
||||
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Включить опцию --first-parent</x:String>
|
||||
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Включить опцию (--first-parent)</x:String>
|
||||
<x:String x:Key="Text.Repository.HistoriesLayout" xml:space="preserve">РАСПОЛОЖЕНИЕ</x:String>
|
||||
<x:String x:Key="Text.Repository.HistoriesLayout.Horizontal" xml:space="preserve">Горизонтально</x:String>
|
||||
<x:String x:Key="Text.Repository.HistoriesLayout.Vertical" xml:space="preserve">Вертикально</x:String>
|
||||
|
@ -633,7 +640,7 @@
|
|||
<x:String x:Key="Text.Running" xml:space="preserve">Запуск. Подождите пожалуйста...</x:String>
|
||||
<x:String x:Key="Text.Save" xml:space="preserve">СОХРАНИТЬ</x:String>
|
||||
<x:String x:Key="Text.SaveAs" xml:space="preserve">Сохранить как...</x:String>
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">Исправление успешно сохранено!</x:String>
|
||||
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">Заплатка успешно сохранена!</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories" xml:space="preserve">Сканирование репозиторий</x:String>
|
||||
<x:String x:Key="Text.ScanRepositories.RootDir" xml:space="preserve">Корневой каталог:</x:String>
|
||||
<x:String x:Key="Text.SHALinkCM.CopySHA" xml:space="preserve">Копировать SHA</x:String>
|
||||
|
@ -667,6 +674,7 @@
|
|||
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Принять</x:String>
|
||||
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Отбросить</x:String>
|
||||
<x:String x:Key="Text.StashCM.Pop" xml:space="preserve">Применить</x:String>
|
||||
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Сохранить как заплатку...</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Отбросить тайник</x:String>
|
||||
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Отбросить:</x:String>
|
||||
<x:String x:Key="Text.Stashes" xml:space="preserve">Отложенные</x:String>
|
||||
|
@ -674,7 +682,7 @@
|
|||
<x:String x:Key="Text.Stashes.Stashes" xml:space="preserve">ОТЛОЖЕННЫЕ</x:String>
|
||||
<x:String x:Key="Text.Statistics" xml:space="preserve">Статистика</x:String>
|
||||
<x:String x:Key="Text.Statistics.CommitAmount" xml:space="preserve">РЕВИЗИИ</x:String>
|
||||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">РЕВИЗОРЫ(ИСПОЛНИТЕЛИ)</x:String>
|
||||
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">РЕВИЗОРЫ (ИСПОЛНИТЕЛИ)</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">МЕСЯЦ</x:String>
|
||||
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">НЕДЕЛЯ</x:String>
|
||||
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">РЕВИЗИИ: </x:String>
|
||||
|
@ -697,10 +705,10 @@
|
|||
<x:String x:Key="Text.URL" xml:space="preserve">Сетевой адрес:</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">Обновление подмодулей</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.All" xml:space="preserve">Все подмодули</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.Init" xml:space="preserve">Инициализировать по необходимости</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.Init" xml:space="preserve">Создавать по необходимости</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.Recursive" xml:space="preserve">Рекурсивно</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Подмодуль:</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Использовать опцию '--remote'</x:String>
|
||||
<x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Использовать опцию (--remote)</x:String>
|
||||
<x:String x:Key="Text.Warn" xml:space="preserve">Предупреждение</x:String>
|
||||
<x:String x:Key="Text.Welcome" xml:space="preserve">Приветствие</x:String>
|
||||
<x:String x:Key="Text.Welcome.AddRootFolder" xml:space="preserve">Создать группу</x:String>
|
||||
|
|
|
@ -467,6 +467,7 @@
|
|||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">启用流式输出</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外观配置</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">缺省字体</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">编辑器制表符宽度</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">字体大小</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">默认</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">代码编辑器</x:String>
|
||||
|
|
|
@ -467,6 +467,7 @@
|
|||
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">啟用串流輸出</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">外觀設定</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">預設字型</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">編輯器制表符寬度</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">字型大小</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">預設</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">程式碼</x:String>
|
||||
|
|
|
@ -1299,6 +1299,8 @@
|
|||
<Setter Property="MinHeight" Value="0"/>
|
||||
<Setter Property="Height" Value="28"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
|
||||
</Style>
|
||||
<Style Selector="^:focus-within /template/ ButtonSpinner#PART_Spinner">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Threading;
|
||||
|
||||
|
@ -57,7 +58,18 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public string GetCommitMessage(string sha)
|
||||
{
|
||||
if (_commitMessages.TryGetValue(sha, out var msg))
|
||||
return msg;
|
||||
|
||||
msg = new Commands.QueryCommitFullMessage(_repo, sha).Result();
|
||||
_commitMessages[sha] = msg;
|
||||
return msg;
|
||||
}
|
||||
|
||||
private readonly string _repo;
|
||||
private Models.BlameData _data = null;
|
||||
private Dictionary<string, string> _commitMessages = new Dictionary<string, string>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ using System.IO;
|
|||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
@ -17,12 +16,6 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
public partial class CommitDetail : ObservableObject
|
||||
{
|
||||
public DiffContext DiffContext
|
||||
{
|
||||
get => _diffContext;
|
||||
private set => SetProperty(ref _diffContext, value);
|
||||
}
|
||||
|
||||
public int ActivePageIndex
|
||||
{
|
||||
get => _repo.CommitDetailActivePageIndex;
|
||||
|
@ -46,7 +39,7 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public string FullMessage
|
||||
public Models.CommitFullMessage FullMessage
|
||||
{
|
||||
get => _fullMessage;
|
||||
private set => SetProperty(ref _fullMessage, value);
|
||||
|
@ -58,6 +51,18 @@ namespace SourceGit.ViewModels
|
|||
private set => SetProperty(ref _signInfo, value);
|
||||
}
|
||||
|
||||
public List<Models.CommitLink> WebLinks
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = [];
|
||||
|
||||
public List<string> Children
|
||||
{
|
||||
get => _children;
|
||||
private set => SetProperty(ref _children, value);
|
||||
}
|
||||
|
||||
public List<Models.Change> Changes
|
||||
{
|
||||
get => _changes;
|
||||
|
@ -85,11 +90,11 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
public AvaloniaList<string> Children
|
||||
public DiffContext DiffContext
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = [];
|
||||
get => _diffContext;
|
||||
private set => SetProperty(ref _diffContext, value);
|
||||
}
|
||||
|
||||
public string SearchChangeFilter
|
||||
{
|
||||
|
@ -109,73 +114,20 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _viewRevisionFileContent, value);
|
||||
}
|
||||
|
||||
public AvaloniaList<Models.CommitLink> WebLinks
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = [];
|
||||
|
||||
public AvaloniaList<Models.IssueTrackerRule> IssueTrackerRules
|
||||
{
|
||||
get => _repo.Settings?.IssueTrackerRules;
|
||||
}
|
||||
|
||||
public string RevisionFileSearchFilter
|
||||
{
|
||||
get => _revisionFileSearchFilter;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _revisionFileSearchFilter, value))
|
||||
{
|
||||
RevisionFileSearchSuggestion.Clear();
|
||||
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
if (_revisionFiles.Count == 0)
|
||||
{
|
||||
var sha = Commit.SHA;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result();
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (sha == Commit.SHA)
|
||||
{
|
||||
_revisionFiles.Clear();
|
||||
_revisionFiles.AddRange(files);
|
||||
|
||||
if (!string.IsNullOrEmpty(_revisionFileSearchFilter))
|
||||
UpdateRevisionFileSearchSuggestion();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateRevisionFileSearchSuggestion();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IsRevisionFileSearchSuggestionOpen = false;
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
RefreshRevisionSearchSuggestion();
|
||||
}
|
||||
}
|
||||
|
||||
public AvaloniaList<string> RevisionFileSearchSuggestion
|
||||
public List<string> RevisionFileSearchSuggestion
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = [];
|
||||
|
||||
public bool IsRevisionFileSearchSuggestionOpen
|
||||
{
|
||||
get => _isRevisionFileSearchSuggestionOpen;
|
||||
set => SetProperty(ref _isRevisionFileSearchSuggestionOpen, value);
|
||||
get => _revisionFileSearchSuggestion;
|
||||
private set => SetProperty(ref _revisionFileSearchSuggestion, value);
|
||||
}
|
||||
|
||||
public CommitDetail(Repository repo)
|
||||
|
@ -212,23 +164,17 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
_repo = null;
|
||||
_commit = null;
|
||||
|
||||
if (_changes != null)
|
||||
_changes.Clear();
|
||||
if (_visibleChanges != null)
|
||||
_visibleChanges.Clear();
|
||||
if (_selectedChanges != null)
|
||||
_selectedChanges.Clear();
|
||||
|
||||
_changes = null;
|
||||
_visibleChanges = null;
|
||||
_selectedChanges = null;
|
||||
_signInfo = null;
|
||||
_searchChangeFilter = null;
|
||||
_diffContext = null;
|
||||
_viewRevisionFileContent = null;
|
||||
_cancelToken = null;
|
||||
|
||||
WebLinks.Clear();
|
||||
_revisionFiles.Clear();
|
||||
RevisionFileSearchSuggestion.Clear();
|
||||
_revisionFiles = null;
|
||||
_revisionFileSearchSuggestion = null;
|
||||
}
|
||||
|
||||
public void NavigateTo(string commitSHA)
|
||||
|
@ -251,6 +197,11 @@ namespace SourceGit.ViewModels
|
|||
RevisionFileSearchFilter = string.Empty;
|
||||
}
|
||||
|
||||
public void CancelRevisionFileSuggestions()
|
||||
{
|
||||
RevisionFileSearchSuggestion = null;
|
||||
}
|
||||
|
||||
public Models.Commit GetParent(string sha)
|
||||
{
|
||||
return new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
|
||||
|
@ -322,7 +273,12 @@ namespace SourceGit.ViewModels
|
|||
if (commit != null)
|
||||
{
|
||||
var body = new Commands.QueryCommitFullMessage(submoduleRoot, file.SHA).Result();
|
||||
var submodule = new Models.RevisionSubmodule() { Commit = commit, FullMessage = body };
|
||||
var submodule = new Models.RevisionSubmodule()
|
||||
{
|
||||
Commit = commit,
|
||||
FullMessage = new Models.CommitFullMessage { Message = body }
|
||||
};
|
||||
|
||||
Dispatcher.UIThread.Invoke(() => ViewRevisionFileContent = submodule);
|
||||
}
|
||||
else
|
||||
|
@ -332,7 +288,7 @@ namespace SourceGit.ViewModels
|
|||
ViewRevisionFileContent = new Models.RevisionSubmodule()
|
||||
{
|
||||
Commit = new Models.Commit() { SHA = file.SHA },
|
||||
FullMessage = string.Empty,
|
||||
FullMessage = null,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -622,23 +578,22 @@ namespace SourceGit.ViewModels
|
|||
private void Refresh()
|
||||
{
|
||||
_changes = null;
|
||||
_revisionFiles.Clear();
|
||||
_revisionFiles = null;
|
||||
|
||||
SignInfo = null;
|
||||
ViewRevisionFileContent = null;
|
||||
Children.Clear();
|
||||
Children = null;
|
||||
RevisionFileSearchFilter = string.Empty;
|
||||
IsRevisionFileSearchSuggestionOpen = false;
|
||||
|
||||
GC.Collect();
|
||||
RevisionFileSearchSuggestion = null;
|
||||
|
||||
if (_commit == null)
|
||||
return;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var fullMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result();
|
||||
Dispatcher.UIThread.Invoke(() => FullMessage = fullMessage);
|
||||
var message = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result();
|
||||
var links = ParseLinksInMessage(message);
|
||||
Dispatcher.UIThread.Invoke(() => FullMessage = new Models.CommitFullMessage { Message = message, Links = links });
|
||||
});
|
||||
|
||||
Task.Run(() =>
|
||||
|
@ -694,6 +649,49 @@ namespace SourceGit.ViewModels
|
|||
});
|
||||
}
|
||||
|
||||
private List<Models.Hyperlink> ParseLinksInMessage(string message)
|
||||
{
|
||||
var links = new List<Models.Hyperlink>();
|
||||
if (_repo.Settings.IssueTrackerRules is { Count: > 0 } rules)
|
||||
{
|
||||
foreach (var rule in rules)
|
||||
rule.Matches(links, message);
|
||||
}
|
||||
|
||||
var matches = REG_SHA_FORMAT().Matches(message);
|
||||
for (int i = 0; i < matches.Count; i++)
|
||||
{
|
||||
var match = matches[i];
|
||||
if (!match.Success)
|
||||
continue;
|
||||
|
||||
var start = match.Index;
|
||||
var len = match.Length;
|
||||
var intersect = false;
|
||||
foreach (var link in links)
|
||||
{
|
||||
if (link.Intersect(start, len))
|
||||
{
|
||||
intersect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (intersect)
|
||||
continue;
|
||||
|
||||
var sha = match.Groups[1].Value;
|
||||
var isCommitSHA = new Commands.IsCommitSHA(_repo.FullPath, sha).Result();
|
||||
if (isCommitSHA)
|
||||
links.Add(new Models.Hyperlink(start, len, sha, true));
|
||||
}
|
||||
|
||||
if (links.Count > 0)
|
||||
links.Sort((l, r) => l.Start - r.Start);
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
private void RefreshVisibleChanges()
|
||||
{
|
||||
if (_changes == null)
|
||||
|
@ -800,7 +798,44 @@ namespace SourceGit.ViewModels
|
|||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
}
|
||||
|
||||
private void UpdateRevisionFileSearchSuggestion()
|
||||
private void RefreshRevisionSearchSuggestion()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_revisionFileSearchFilter))
|
||||
{
|
||||
if (_revisionFiles == null)
|
||||
{
|
||||
var sha = Commit.SHA;
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var files = new Commands.QueryRevisionFileNames(_repo.FullPath, sha).Result();
|
||||
var filesList = new List<string>();
|
||||
filesList.AddRange(files);
|
||||
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
if (sha == Commit.SHA)
|
||||
{
|
||||
_revisionFiles = filesList;
|
||||
if (!string.IsNullOrEmpty(_revisionFileSearchFilter))
|
||||
CalcRevisionFileSearchSuggestion();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
CalcRevisionFileSearchSuggestion();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RevisionFileSearchSuggestion = null;
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
private void CalcRevisionFileSearchSuggestion()
|
||||
{
|
||||
var suggestion = new List<string>();
|
||||
foreach (var file in _revisionFiles)
|
||||
|
@ -813,11 +848,12 @@ namespace SourceGit.ViewModels
|
|||
break;
|
||||
}
|
||||
|
||||
RevisionFileSearchSuggestion.Clear();
|
||||
RevisionFileSearchSuggestion.AddRange(suggestion);
|
||||
IsRevisionFileSearchSuggestionOpen = suggestion.Count > 0;
|
||||
RevisionFileSearchSuggestion = suggestion;
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")]
|
||||
private static partial Regex REG_SHA_FORMAT();
|
||||
|
||||
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
|
||||
private static partial Regex REG_LFS_FORMAT();
|
||||
|
||||
|
@ -828,8 +864,9 @@ namespace SourceGit.ViewModels
|
|||
|
||||
private Repository _repo = null;
|
||||
private Models.Commit _commit = null;
|
||||
private string _fullMessage = string.Empty;
|
||||
private Models.CommitFullMessage _fullMessage = null;
|
||||
private Models.CommitSignInfo _signInfo = null;
|
||||
private List<string> _children = null;
|
||||
private List<Models.Change> _changes = null;
|
||||
private List<Models.Change> _visibleChanges = null;
|
||||
private List<Models.Change> _selectedChanges = null;
|
||||
|
@ -837,8 +874,8 @@ namespace SourceGit.ViewModels
|
|||
private DiffContext _diffContext = null;
|
||||
private object _viewRevisionFileContent = null;
|
||||
private Commands.Command.CancelToken _cancelToken = null;
|
||||
private List<string> _revisionFiles = [];
|
||||
private List<string> _revisionFiles = null;
|
||||
private string _revisionFileSearchFilter = string.Empty;
|
||||
private bool _isRevisionFileSearchSuggestionOpen = false;
|
||||
private List<string> _revisionFileSearchSuggestion = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,14 +35,8 @@
|
|||
}
|
||||
else if (context is RebaseInProgress rebase)
|
||||
{
|
||||
Theirs = repo.Branches.Find(x => x.IsLocal && x.Name == rebase.HeadName) ??
|
||||
new Models.Branch()
|
||||
{
|
||||
IsLocal = true,
|
||||
Name = rebase.HeadName,
|
||||
FullName = $"refs/heads/{rebase.HeadName}"
|
||||
};
|
||||
|
||||
var b = repo.Branches.Find(x => x.IsLocal && x.Name == rebase.HeadName);
|
||||
Theirs = (object)b ?? rebase.StoppedAt;
|
||||
Mine = rebase.Onto;
|
||||
}
|
||||
else if (context is RevertInProgress revert)
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
_isTextDiff = previous._isTextDiff;
|
||||
_content = previous._content;
|
||||
_fileModeChange = previous._fileModeChange;
|
||||
_unifiedLines = previous._unifiedLines;
|
||||
_ignoreWhitespace = previous._ignoreWhitespace;
|
||||
_info = previous._info;
|
||||
|
@ -234,13 +235,17 @@ namespace SourceGit.ViewModels
|
|||
if (commit != null)
|
||||
{
|
||||
var body = new Commands.QueryCommitFullMessage(repo, sha).Result();
|
||||
return new Models.RevisionSubmodule() { Commit = commit, FullMessage = body };
|
||||
return new Models.RevisionSubmodule()
|
||||
{
|
||||
Commit = commit,
|
||||
FullMessage = new Models.CommitFullMessage { Message = body }
|
||||
};
|
||||
}
|
||||
|
||||
return new Models.RevisionSubmodule()
|
||||
{
|
||||
Commit = new Models.Commit() { SHA = sha },
|
||||
FullMessage = string.Empty,
|
||||
FullMessage = null,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -123,12 +123,20 @@ namespace SourceGit.ViewModels
|
|||
if (commit != null)
|
||||
{
|
||||
var message = new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result();
|
||||
var module = new Models.RevisionSubmodule() { Commit = commit, FullMessage = message };
|
||||
var module = new Models.RevisionSubmodule()
|
||||
{
|
||||
Commit = commit,
|
||||
FullMessage = new Models.CommitFullMessage { Message = message }
|
||||
};
|
||||
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
|
||||
}
|
||||
else
|
||||
{
|
||||
var module = new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = obj.SHA }, FullMessage = "" };
|
||||
var module = new Models.RevisionSubmodule()
|
||||
{
|
||||
Commit = new Models.Commit() { SHA = obj.SHA },
|
||||
FullMessage = null
|
||||
};
|
||||
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -107,19 +107,24 @@ namespace SourceGit.ViewModels
|
|||
{
|
||||
_gitDir = repo.GitDir;
|
||||
|
||||
var stoppedSHAPath = Path.Combine(repo.GitDir, "rebase-merge", "stopped-sha");
|
||||
if (File.Exists(stoppedSHAPath))
|
||||
{
|
||||
var stoppedSHA = File.ReadAllText(stoppedSHAPath).Trim();
|
||||
StoppedAt = new Commands.QuerySingleCommit(repo.FullPath, stoppedSHA).Result() ?? new Models.Commit() { SHA = stoppedSHA };
|
||||
}
|
||||
|
||||
var ontoSHA = File.ReadAllText(Path.Combine(repo.GitDir, "rebase-merge", "onto")).Trim();
|
||||
Onto = new Commands.QuerySingleCommit(repo.FullPath, ontoSHA).Result() ?? new Models.Commit() { SHA = ontoSHA };
|
||||
|
||||
HeadName = File.ReadAllText(Path.Combine(repo.GitDir, "rebase-merge", "head-name")).Trim();
|
||||
if (HeadName.StartsWith("refs/heads/"))
|
||||
HeadName = HeadName.Substring(11);
|
||||
else if (HeadName.StartsWith("refs/tags/"))
|
||||
HeadName = HeadName.Substring(10);
|
||||
|
||||
var stoppedSHAPath = Path.Combine(repo.GitDir, "rebase-merge", "stopped-sha");
|
||||
var stoppedSHA = string.Empty;
|
||||
if (File.Exists(stoppedSHAPath))
|
||||
stoppedSHA = File.ReadAllText(stoppedSHAPath).Trim();
|
||||
else
|
||||
stoppedSHA = new Commands.QueryRevisionByRefName(repo.FullPath, HeadName).Result();
|
||||
|
||||
if (!string.IsNullOrEmpty(stoppedSHA))
|
||||
StoppedAt = new Commands.QuerySingleCommit(repo.FullPath, stoppedSHA).Result() ?? new Models.Commit() { SHA = stoppedSHA };
|
||||
|
||||
var ontoSHA = File.ReadAllText(Path.Combine(repo.GitDir, "rebase-merge", "onto")).Trim();
|
||||
Onto = new Commands.QuerySingleCommit(repo.FullPath, ontoSHA).Result() ?? new Models.Commit() { SHA = ontoSHA };
|
||||
}
|
||||
|
||||
public override bool Continue()
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var commits = new Commands.QueryCommitsWithFullMessage(repoPath, $"{on.SHA}..HEAD").Result();
|
||||
var commits = new Commands.QueryCommitsForInteractiveRebase(repoPath, on.SHA).Result();
|
||||
var list = new List<InteractiveRebaseItem>();
|
||||
|
||||
foreach (var c in commits)
|
||||
|
|
|
@ -111,6 +111,12 @@ namespace SourceGit.ViewModels
|
|||
set => SetProperty(ref _editorFontSize, value);
|
||||
}
|
||||
|
||||
public int EditorTabWidth
|
||||
{
|
||||
get => _editorTabWidth;
|
||||
set => SetProperty(ref _editorTabWidth, value);
|
||||
}
|
||||
|
||||
public LayoutInfo Layout
|
||||
{
|
||||
get => _layout;
|
||||
|
@ -649,6 +655,7 @@ namespace SourceGit.ViewModels
|
|||
private bool _useSystemWindowFrame = false;
|
||||
private double _defaultFontSize = 13;
|
||||
private double _editorFontSize = 13;
|
||||
private int _editorTabWidth = 4;
|
||||
private LayoutInfo _layout = new LayoutInfo();
|
||||
|
||||
private int _maxHistoryCommits = 20000;
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace SourceGit.ViewModels
|
|||
public Models.Branch SelectedBranch
|
||||
{
|
||||
get => _selectedBranch;
|
||||
set => SetProperty(ref _selectedBranch, value);
|
||||
set => SetProperty(ref _selectedBranch, value, true);
|
||||
}
|
||||
|
||||
public Models.DealWithLocalChanges PreAction
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace SourceGit.ViewModels
|
|||
get => _selectedLocalBranch;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedLocalBranch, value))
|
||||
if (SetProperty(ref _selectedLocalBranch, value, true))
|
||||
AutoSelectBranchByRemote();
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ namespace SourceGit.ViewModels
|
|||
get => _selectedRemote;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedRemote, value))
|
||||
if (SetProperty(ref _selectedRemote, value, true))
|
||||
AutoSelectBranchByRemote();
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ namespace SourceGit.ViewModels
|
|||
get => _selectedRemoteBranch;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedRemoteBranch, value))
|
||||
if (SetProperty(ref _selectedRemoteBranch, value, true))
|
||||
IsSetTrackOptionVisible = value != null && _selectedLocalBranch.Upstream != value.FullName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1012,7 +1012,7 @@ namespace SourceGit.ViewModels
|
|||
|
||||
var filters = _settings.BuildHistoriesFilter();
|
||||
if (string.IsNullOrEmpty(filters))
|
||||
builder.Append("--branches --remotes --tags");
|
||||
builder.Append("--branches --remotes --tags HEAD");
|
||||
else
|
||||
builder.Append(filters);
|
||||
|
||||
|
|
|
@ -440,6 +440,8 @@ namespace SourceGit.ViewModels
|
|||
|
||||
public void ContinueMerge()
|
||||
{
|
||||
IsCommitting = true;
|
||||
|
||||
if (_inProgressContext != null)
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
@ -456,17 +458,21 @@ namespace SourceGit.ViewModels
|
|||
CommitMessage = string.Empty;
|
||||
|
||||
_repo.SetWatcherEnabled(true);
|
||||
IsCommitting = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
IsCommitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SkipMerge()
|
||||
{
|
||||
IsCommitting = true;
|
||||
|
||||
if (_inProgressContext != null)
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
@ -479,17 +485,21 @@ namespace SourceGit.ViewModels
|
|||
CommitMessage = string.Empty;
|
||||
|
||||
_repo.SetWatcherEnabled(true);
|
||||
IsCommitting = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
IsCommitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void AbortMerge()
|
||||
{
|
||||
IsCommitting = true;
|
||||
|
||||
if (_inProgressContext != null)
|
||||
{
|
||||
_repo.SetWatcherEnabled(false);
|
||||
|
@ -502,12 +512,14 @@ namespace SourceGit.ViewModels
|
|||
CommitMessage = string.Empty;
|
||||
|
||||
_repo.SetWatcherEnabled(true);
|
||||
IsCommitting = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
_repo.MarkWorkingCopyDirtyManually();
|
||||
IsCommitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.About"
|
||||
x:DataType="v:About"
|
||||
x:Name="ThisControl"
|
||||
Icon="/App.ico"
|
||||
Title="{DynamicResource Text.About}"
|
||||
SizeToContent="WidthAndHeight"
|
||||
|
@ -13,7 +13,7 @@
|
|||
WindowStartupLocation="CenterScreen">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<!-- TitleBar -->
|
||||
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !UseSystemWindowFrame}">
|
||||
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
|
||||
<Border Background="{DynamicResource Brush.TitleBar}"
|
||||
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
|
||||
PointerPressed="BeginMoveWindow"/>
|
||||
|
@ -46,13 +46,13 @@
|
|||
<StackPanel Height="48" Orientation="Horizontal">
|
||||
<TextBlock Classes="bold" Text="SourceGit" FontSize="32" />
|
||||
<Border Margin="12,0,0,0" Height="20" CornerRadius="10" Background="{DynamicResource Brush.Accent}" Effect="drop-shadow(0 0 6 #40000000)">
|
||||
<TextBlock Classes="primary" Margin="8,0" Text="{Binding Version}" FontSize="12" Foreground="White"/>
|
||||
<TextBlock x:Name="TxtVersion" Classes="primary" Margin="8,0" FontSize="12" Foreground="White"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Margin="2,0,0,0" Text="{DynamicResource Text.About.SubTitle}" FontSize="16"/>
|
||||
|
||||
<TextBlock Margin="2,8,0,0" Text="{Binding Copyright}" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
<TextBlock x:Name="TxtCopyright" Margin="2,8,0,0" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
|
||||
<StackPanel Orientation="Vertical" Margin="0,24,0,0">
|
||||
<StackPanel Orientation="Horizontal" Height="18">
|
||||
|
|
|
@ -5,30 +5,18 @@ namespace SourceGit.Views
|
|||
{
|
||||
public partial class About : ChromelessWindow
|
||||
{
|
||||
public string Version
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Copyright
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public About()
|
||||
{
|
||||
var ver = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
if (ver != null)
|
||||
Version = $"{ver.Major}.{ver.Minor}";
|
||||
var attributes = Assembly.GetExecutingAssembly()
|
||||
.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
|
||||
if (attributes.Length > 0)
|
||||
Copyright = ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
|
||||
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var ver = assembly.GetName().Version;
|
||||
if (ver != null)
|
||||
TxtVersion.Text = $"{ver.Major}.{ver.Minor:D2}";
|
||||
|
||||
var copyright = assembly.GetCustomAttribute<AssemblyCopyrightAttribute>();
|
||||
if (copyright != null)
|
||||
TxtCopyright.Text = copyright.Copyright;
|
||||
}
|
||||
|
||||
private void OnVisitAvaloniaUI(object _, PointerPressedEventArgs e)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.Askpass"
|
||||
x:DataType="v:Askpass"
|
||||
x:Name="ThisControl"
|
||||
Icon="/App.ico"
|
||||
Title="{DynamicResource Text.Askpass}"
|
||||
SizeToContent="WidthAndHeight"
|
||||
|
@ -13,7 +13,7 @@
|
|||
WindowStartupLocation="CenterScreen">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<!-- TitleBar -->
|
||||
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !UseSystemWindowFrame}">
|
||||
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
|
||||
<Border Background="{DynamicResource Brush.TitleBar}"
|
||||
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
|
||||
PointerPressed="BeginMoveWindow"/>
|
||||
|
@ -36,23 +36,23 @@
|
|||
|
||||
<StackPanel Grid.Row="1" Margin="0,16" Orientation="Vertical">
|
||||
<Border Margin="16,0">
|
||||
<TextBlock Text="{Binding Description}" TextWrapping="Wrap"/>
|
||||
<TextBlock x:Name="TxtDescription" Text="Enter passphrase:" TextWrapping="Wrap"/>
|
||||
</Border>
|
||||
|
||||
<TextBox Margin="16"
|
||||
MinWidth="300"
|
||||
Height="32"
|
||||
<TextBox x:Name="TxtPassphrase"
|
||||
Margin="16"
|
||||
MinWidth="300"
|
||||
Height="32"
|
||||
Focusable="True"
|
||||
Text="{Binding Passphrase, Mode=TwoWay}"
|
||||
PasswordChar="*"
|
||||
RevealPassword="{Binding ShowPassword, Mode=OneWay}"
|
||||
RevealPassword="{Binding #ToggleShowPassword.IsChecked, Mode=OneWay}"
|
||||
HorizontalAlignment="Stretch"
|
||||
v:AutoFocusBehaviour.IsEnabled="True">
|
||||
<TextBox.InnerRightContent>
|
||||
<ToggleButton Grid.Column="6"
|
||||
x:Name="ToggleShowPassword"
|
||||
Classes="toggle_untracked"
|
||||
Width="26" Height="14"
|
||||
IsChecked="{Binding ShowPassword, Mode=TwoWay}"/>
|
||||
Width="26" Height="14"/>
|
||||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
|
||||
|
|
|
@ -1,43 +1,12 @@
|
|||
using System;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Askpass : ChromelessWindow
|
||||
{
|
||||
public static readonly StyledProperty<bool> ShowPasswordProperty =
|
||||
AvaloniaProperty.Register<Askpass, bool>(nameof(ShowPassword));
|
||||
|
||||
public bool ShowPassword
|
||||
{
|
||||
get => GetValue(ShowPasswordProperty);
|
||||
set => SetValue(ShowPasswordProperty, value);
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = string.Empty;
|
||||
|
||||
public string Passphrase
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = string.Empty;
|
||||
|
||||
public Askpass()
|
||||
{
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public Askpass(string description)
|
||||
{
|
||||
Description = description;
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
@ -49,7 +18,8 @@ namespace SourceGit.Views
|
|||
|
||||
private void EnterPassword(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
Console.Out.Write($"{Passphrase}\n");
|
||||
var passphrase = TxtPassphrase.Text ?? string.Empty;
|
||||
Console.Out.Write($"{passphrase}\n");
|
||||
App.Quit(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,8 +58,9 @@
|
|||
Foreground="{DynamicResource Brush.FG1}"
|
||||
FontFamily="{DynamicResource Fonts.Monospace}"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
|
||||
TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
|
||||
BlameData="{Binding Data}"/>
|
||||
|
||||
|
||||
<!-- Not supported mask (for binary files) -->
|
||||
<StackPanel Orientation="Vertical"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
|
|
|
@ -175,12 +175,21 @@ namespace SourceGit.Views
|
|||
if (rect.Contains(pos))
|
||||
{
|
||||
Cursor = Cursor.Parse("Hand");
|
||||
|
||||
if (DataContext is ViewModels.Blame blame)
|
||||
{
|
||||
var msg = blame.GetCommitMessage(info.CommitSHA);
|
||||
ToolTip.SetTip(this, msg);
|
||||
ToolTip.SetIsOpen(this, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cursor = Cursor.Default;
|
||||
Cursor = Cursor.Default;
|
||||
ToolTip.SetIsOpen(this, false);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
|
@ -230,9 +239,9 @@ namespace SourceGit.Views
|
|||
private readonly BlameTextEditor _editor = null;
|
||||
}
|
||||
|
||||
public class VerticalSeperatorMargin : AbstractMargin
|
||||
public class VerticalSeparatorMargin : AbstractMargin
|
||||
{
|
||||
public VerticalSeperatorMargin(BlameTextEditor editor)
|
||||
public VerticalSeparatorMargin(BlameTextEditor editor)
|
||||
{
|
||||
_editor = editor;
|
||||
}
|
||||
|
@ -260,6 +269,15 @@ namespace SourceGit.Views
|
|||
set => SetValue(BlameDataProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<int> TabWidthProperty =
|
||||
AvaloniaProperty.Register<BlameTextEditor, int>(nameof(TabWidth), 4);
|
||||
|
||||
public int TabWidth
|
||||
{
|
||||
get => GetValue(TabWidthProperty);
|
||||
set => SetValue(TabWidthProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||
|
||||
public BlameTextEditor() : base(new TextArea(), new TextDocument())
|
||||
|
@ -268,20 +286,22 @@ namespace SourceGit.Views
|
|||
ShowLineNumbers = false;
|
||||
WordWrap = false;
|
||||
|
||||
Options.IndentationSize = TabWidth;
|
||||
Options.EnableHyperlinks = false;
|
||||
Options.EnableEmailHyperlinks = false;
|
||||
|
||||
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
||||
|
||||
TextArea.LeftMargins.Add(new LineNumberMargin() { Margin = new Thickness(8, 0) });
|
||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
||||
TextArea.LeftMargins.Add(new VerticalSeparatorMargin(this));
|
||||
TextArea.LeftMargins.Add(new CommitInfoMargin(this) { Margin = new Thickness(8, 0) });
|
||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
||||
TextArea.LeftMargins.Add(new VerticalSeparatorMargin(this));
|
||||
TextArea.Caret.PositionChanged += OnTextAreaCaretPositionChanged;
|
||||
TextArea.LayoutUpdated += OnTextAreaLayoutUpdated;
|
||||
TextArea.PointerWheelChanged += OnTextAreaPointerWheelChanged;
|
||||
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
||||
TextArea.TextView.VisualLinesChanged += OnTextViewVisualLinesChanged;
|
||||
TextArea.TextView.Margin = new Thickness(4, 0);
|
||||
TextArea.TextView.Options.EnableHyperlinks = false;
|
||||
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
|
@ -350,6 +370,10 @@ namespace SourceGit.Views
|
|||
Text = string.Empty;
|
||||
}
|
||||
}
|
||||
else if (change.Property == TabWidthProperty)
|
||||
{
|
||||
Options.IndentationSize = TabWidth;
|
||||
}
|
||||
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
|
||||
{
|
||||
Models.TextMateHelper.SetThemeByApp(_textMate);
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
xmlns:v="using:SourceGit.Views"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="SourceGit.Views.ChangeViewModeSwitcher"
|
||||
x:DataType="v:ChangeViewModeSwitcher">
|
||||
x:Name="ThisControl">
|
||||
<Button Classes="icon_button" ToolTip.Tip="{DynamicResource Text.ChangeDisplayMode}">
|
||||
<Button.Flyout>
|
||||
<MenuFlyout Placement="BottomEdgeAlignedLeft">
|
||||
<MenuItem Header="{DynamicResource Text.ChangeDisplayMode.List}" Command="{Binding SwitchMode}" CommandParameter="{x:Static m:ChangeViewMode.List}">
|
||||
<MenuItem Header="{DynamicResource Text.ChangeDisplayMode.List}" Click="SwitchToList">
|
||||
<MenuItem.Icon>
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.List}"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="{DynamicResource Text.ChangeDisplayMode.Grid}" Command="{Binding SwitchMode}" CommandParameter="{x:Static m:ChangeViewMode.Grid}">
|
||||
<MenuItem Header="{DynamicResource Text.ChangeDisplayMode.Grid}" Click="SwitchToGrid">
|
||||
<MenuItem.Icon>
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Grid}"/>
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="{DynamicResource Text.ChangeDisplayMode.Tree}" Command="{Binding SwitchMode}" CommandParameter="{x:Static m:ChangeViewMode.Tree}">
|
||||
<MenuItem Header="{DynamicResource Text.ChangeDisplayMode.Tree}" Click="SwitchToTree">
|
||||
<MenuItem.Icon>
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Tree}"/>
|
||||
</MenuItem.Icon>
|
||||
|
@ -31,13 +31,13 @@
|
|||
<Grid Width="14" Height="14" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Path Width="14" Height="14"
|
||||
Data="{StaticResource Icons.List}"
|
||||
IsVisible="{Binding ViewMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:ChangeViewMode.List}}"/>
|
||||
IsVisible="{Binding #ThisControl.ViewMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:ChangeViewMode.List}}"/>
|
||||
<Path Width="14" Height="14"
|
||||
Data="{StaticResource Icons.Grid}"
|
||||
IsVisible="{Binding ViewMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:ChangeViewMode.Grid}}"/>
|
||||
IsVisible="{Binding #ThisControl.ViewMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:ChangeViewMode.Grid}}"/>
|
||||
<Path Width="14" Height="14"
|
||||
Data="{StaticResource Icons.Tree}"
|
||||
IsVisible="{Binding ViewMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:ChangeViewMode.Tree}}"/>
|
||||
IsVisible="{Binding #ThisControl.ViewMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:ChangeViewMode.Tree}}"/>
|
||||
</Grid>
|
||||
</Button>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
|
@ -16,13 +17,25 @@ namespace SourceGit.Views
|
|||
|
||||
public ChangeViewModeSwitcher()
|
||||
{
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SwitchMode(object param)
|
||||
private void SwitchToList(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewMode = (Models.ChangeViewMode)param;
|
||||
ViewMode = Models.ChangeViewMode.List;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void SwitchToGrid(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewMode = Models.ChangeViewMode.Grid;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void SwitchToTree(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewMode = Models.ChangeViewMode.Tree;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,8 +95,8 @@
|
|||
</StackPanel>
|
||||
|
||||
<!-- PARENTS -->
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Classes="info_label" VerticalAlignment="Top" Margin="0,4,0,0" Text="{DynamicResource Text.CommitDetail.Info.Parents}" IsVisible="{Binding Parents.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"/>
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Height="24" Margin="12,0,0,0" ItemsSource="{Binding Parents}" IsVisible="{Binding Parents.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}">
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Classes="info_label" VerticalAlignment="Top" Margin="0,4,0,0" Text="{DynamicResource Text.CommitDetail.Info.Parents}" IsVisible="{Binding Parents, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}"/>
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Height="24" Margin="12,0,0,0" ItemsSource="{Binding Parents}" IsVisible="{Binding Parents, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"/>
|
||||
|
@ -133,8 +133,8 @@
|
|||
</ItemsControl>
|
||||
|
||||
<!-- CHILDREN -->
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Classes="info_label" VerticalAlignment="Top" Margin="0,4,0,0" Text="{DynamicResource Text.CommitDetail.Info.Children}" IsVisible="{Binding #ThisControl.Children.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}"/>
|
||||
<ItemsControl Grid.Row="2" Grid.Column="1" Margin="12,0,0,0" ItemsSource="{Binding #ThisControl.Children}" IsVisible="{Binding #ThisControl.Children.Count, Converter={x:Static c:IntConverters.IsGreaterThanZero}}">
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Classes="info_label" VerticalAlignment="Top" Margin="0,4,0,0" Text="{DynamicResource Text.CommitDetail.Info.Children}" IsVisible="{Binding #ThisControl.Children, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}"/>
|
||||
<ItemsControl Grid.Row="2" Grid.Column="1" Margin="12,0,0,0" ItemsSource="{Binding #ThisControl.Children}" IsVisible="{Binding #ThisControl.Children, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" VerticalAlignment="Center" ItemHeight="24"/>
|
||||
|
@ -187,8 +187,7 @@
|
|||
<v:CommitMessagePresenter Grid.Row="4" Grid.Column="1"
|
||||
Margin="12,4,8,0"
|
||||
Classes="primary"
|
||||
Message="{Binding #ThisControl.Message}"
|
||||
IssueTrackerRules="{Binding #ThisControl.IssueTrackerRules}"
|
||||
FullMessage="{Binding #ThisControl.FullMessage}"
|
||||
HorizontalAlignment="Stretch"
|
||||
TextWrapping="Wrap">
|
||||
<v:CommitMessagePresenter.DataTemplates>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
|
@ -11,13 +11,13 @@ namespace SourceGit.Views
|
|||
{
|
||||
public partial class CommitBaseInfo : UserControl
|
||||
{
|
||||
public static readonly StyledProperty<string> MessageProperty =
|
||||
AvaloniaProperty.Register<CommitBaseInfo, string>(nameof(Message), string.Empty);
|
||||
public static readonly StyledProperty<Models.CommitFullMessage> FullMessageProperty =
|
||||
AvaloniaProperty.Register<CommitBaseInfo, Models.CommitFullMessage>(nameof(FullMessage));
|
||||
|
||||
public string Message
|
||||
public Models.CommitFullMessage FullMessage
|
||||
{
|
||||
get => GetValue(MessageProperty);
|
||||
set => SetValue(MessageProperty, value);
|
||||
get => GetValue(FullMessageProperty);
|
||||
set => SetValue(FullMessageProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Models.CommitSignInfo> SignInfoProperty =
|
||||
|
@ -38,28 +38,19 @@ namespace SourceGit.Views
|
|||
set => SetValue(SupportsContainsInProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<AvaloniaList<Models.CommitLink>> WebLinksProperty =
|
||||
AvaloniaProperty.Register<CommitBaseInfo, AvaloniaList<Models.CommitLink>>(nameof(WebLinks));
|
||||
public static readonly StyledProperty<List<Models.CommitLink>> WebLinksProperty =
|
||||
AvaloniaProperty.Register<CommitBaseInfo, List<Models.CommitLink>>(nameof(WebLinks));
|
||||
|
||||
public AvaloniaList<Models.CommitLink> WebLinks
|
||||
public List<Models.CommitLink> WebLinks
|
||||
{
|
||||
get => GetValue(WebLinksProperty);
|
||||
set => SetValue(WebLinksProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<AvaloniaList<Models.IssueTrackerRule>> IssueTrackerRulesProperty =
|
||||
AvaloniaProperty.Register<CommitBaseInfo, AvaloniaList<Models.IssueTrackerRule>>(nameof(IssueTrackerRules));
|
||||
public static readonly StyledProperty<List<string>> ChildrenProperty =
|
||||
AvaloniaProperty.Register<CommitBaseInfo, List<string>>(nameof(Children));
|
||||
|
||||
public AvaloniaList<Models.IssueTrackerRule> IssueTrackerRules
|
||||
{
|
||||
get => GetValue(IssueTrackerRulesProperty);
|
||||
set => SetValue(IssueTrackerRulesProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<AvaloniaList<string>> ChildrenProperty =
|
||||
AvaloniaProperty.Register<CommitBaseInfo, AvaloniaList<string>>(nameof(Children));
|
||||
|
||||
public AvaloniaList<string> Children
|
||||
public List<string> Children
|
||||
{
|
||||
get => GetValue(ChildrenProperty);
|
||||
set => SetValue(ChildrenProperty, value);
|
||||
|
|
|
@ -20,12 +20,11 @@
|
|||
<StackPanel Orientation="Vertical">
|
||||
<!-- Base Information -->
|
||||
<v:CommitBaseInfo Content="{Binding Commit}"
|
||||
Message="{Binding FullMessage}"
|
||||
FullMessage="{Binding FullMessage}"
|
||||
SignInfo="{Binding SignInfo}"
|
||||
SupportsContainsIn="True"
|
||||
WebLinks="{Binding WebLinks}"
|
||||
Children="{Binding Children}"
|
||||
IssueTrackerRules="{Binding IssueTrackerRules}"/>
|
||||
Children="{Binding Children}"/>
|
||||
|
||||
<!-- Line -->
|
||||
<Rectangle Height=".65" Margin="8" Fill="{DynamicResource Brush.Border2}"/>
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Documents;
|
||||
using Avalonia.Input;
|
||||
|
@ -13,27 +11,15 @@ using Avalonia.VisualTree;
|
|||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CommitMessagePresenter : SelectableTextBlock
|
||||
public class CommitMessagePresenter : SelectableTextBlock
|
||||
{
|
||||
[GeneratedRegex(@"\b([0-9a-fA-F]{6,40})\b")]
|
||||
private static partial Regex REG_SHA_FORMAT();
|
||||
public static readonly StyledProperty<Models.CommitFullMessage> FullMessageProperty =
|
||||
AvaloniaProperty.Register<CommitMessagePresenter, Models.CommitFullMessage>(nameof(FullMessage));
|
||||
|
||||
public static readonly StyledProperty<string> MessageProperty =
|
||||
AvaloniaProperty.Register<CommitMessagePresenter, string>(nameof(Message));
|
||||
|
||||
public string Message
|
||||
public Models.CommitFullMessage FullMessage
|
||||
{
|
||||
get => GetValue(MessageProperty);
|
||||
set => SetValue(MessageProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<AvaloniaList<Models.IssueTrackerRule>> IssueTrackerRulesProperty =
|
||||
AvaloniaProperty.Register<CommitMessagePresenter, AvaloniaList<Models.IssueTrackerRule>>(nameof(IssueTrackerRules));
|
||||
|
||||
public AvaloniaList<Models.IssueTrackerRule> IssueTrackerRules
|
||||
{
|
||||
get => GetValue(IssueTrackerRulesProperty);
|
||||
set => SetValue(IssueTrackerRulesProperty, value);
|
||||
get => GetValue(FullMessageProperty);
|
||||
set => SetValue(FullMessageProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(SelectableTextBlock);
|
||||
|
@ -42,69 +28,36 @@ namespace SourceGit.Views
|
|||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == MessageProperty || change.Property == IssueTrackerRulesProperty)
|
||||
if (change.Property == FullMessageProperty)
|
||||
{
|
||||
Inlines!.Clear();
|
||||
_inlineCommits.Clear();
|
||||
_matches = null;
|
||||
_lastHover = null;
|
||||
ClearHoveredIssueLink();
|
||||
|
||||
var message = Message;
|
||||
var message = FullMessage?.Message;
|
||||
if (string.IsNullOrEmpty(message))
|
||||
return;
|
||||
|
||||
var matches = new List<Models.Hyperlink>();
|
||||
if (IssueTrackerRules is { Count: > 0 } rules)
|
||||
{
|
||||
foreach (var rule in rules)
|
||||
rule.Matches(matches, message);
|
||||
}
|
||||
|
||||
var shas = REG_SHA_FORMAT().Matches(message);
|
||||
for (int i = 0; i < shas.Count; i++)
|
||||
{
|
||||
var sha = shas[i];
|
||||
if (!sha.Success)
|
||||
continue;
|
||||
|
||||
var start = sha.Index;
|
||||
var len = sha.Length;
|
||||
var intersect = false;
|
||||
foreach (var match in matches)
|
||||
{
|
||||
if (match.Intersect(start, len))
|
||||
{
|
||||
intersect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!intersect)
|
||||
matches.Add(new Models.Hyperlink(start, len, sha.Groups[1].Value, true));
|
||||
}
|
||||
|
||||
if (matches.Count == 0)
|
||||
var links = FullMessage?.Links;
|
||||
if (links == null || links.Count == 0)
|
||||
{
|
||||
Inlines.Add(new Run(message));
|
||||
return;
|
||||
}
|
||||
|
||||
matches.Sort((l, r) => l.Start - r.Start);
|
||||
_matches = matches;
|
||||
|
||||
var inlines = new List<Inline>();
|
||||
var pos = 0;
|
||||
foreach (var match in matches)
|
||||
foreach (var link in links)
|
||||
{
|
||||
if (match.Start > pos)
|
||||
inlines.Add(new Run(message.Substring(pos, match.Start - pos)));
|
||||
if (link.Start > pos)
|
||||
inlines.Add(new Run(message.Substring(pos, link.Start - pos)));
|
||||
|
||||
var link = new Run(message.Substring(match.Start, match.Length));
|
||||
link.Classes.Add(match.IsCommitSHA ? "commit_link" : "issue_link");
|
||||
inlines.Add(link);
|
||||
var run = new Run(message.Substring(link.Start, link.Length));
|
||||
run.Classes.Add(link.IsCommitSHA ? "commit_link" : "issue_link");
|
||||
inlines.Add(run);
|
||||
|
||||
pos = match.Start + match.Length;
|
||||
pos = link.Start + link.Length;
|
||||
}
|
||||
|
||||
if (pos < message.Length)
|
||||
|
@ -134,7 +87,7 @@ namespace SourceGit.Views
|
|||
scrollViewer.LineDown();
|
||||
}
|
||||
}
|
||||
else if (_matches != null)
|
||||
else if (FullMessage is { Links: { Count: > 0 } links })
|
||||
{
|
||||
var point = e.GetPosition(this) - new Point(Padding.Left, Padding.Top);
|
||||
var x = Math.Min(Math.Max(point.X, 0), Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0));
|
||||
|
@ -142,25 +95,25 @@ namespace SourceGit.Views
|
|||
point = new Point(x, y);
|
||||
|
||||
var pos = TextLayout.HitTestPoint(point).TextPosition;
|
||||
foreach (var match in _matches)
|
||||
foreach (var link in links)
|
||||
{
|
||||
if (!match.Intersect(pos, 1))
|
||||
if (!link.Intersect(pos, 1))
|
||||
continue;
|
||||
|
||||
if (match == _lastHover)
|
||||
if (link == _lastHover)
|
||||
return;
|
||||
|
||||
SetCurrentValue(CursorProperty, Cursor.Parse("Hand"));
|
||||
|
||||
_lastHover = match;
|
||||
if (!match.IsCommitSHA)
|
||||
_lastHover = link;
|
||||
if (!link.IsCommitSHA)
|
||||
{
|
||||
ToolTip.SetTip(this, match.Link);
|
||||
ToolTip.SetTip(this, link.Link);
|
||||
ToolTip.SetIsOpen(this, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessHoverCommitLink(match);
|
||||
ProcessHoverCommitLink(link);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -361,7 +314,6 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
private List<Models.Hyperlink> _matches = null;
|
||||
private Models.Hyperlink _lastHover = null;
|
||||
private Dictionary<string, Models.Commit> _inlineCommits = new();
|
||||
}
|
||||
|
|
|
@ -257,7 +257,7 @@
|
|||
<ContentControl.DataTemplates>
|
||||
<DataTemplate DataType="m:RevisionSubmodule">
|
||||
<Border Margin="0,0,0,8" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Background="{DynamicResource Brush.Window}">
|
||||
<v:CommitBaseInfo MaxHeight="256" Margin="0,0,0,4" Content="{Binding Commit}" Message="{Binding FullMessage}"/>
|
||||
<v:CommitBaseInfo MaxHeight="256" Margin="0,0,0,4" Content="{Binding Commit}" FullMessage="{Binding FullMessage}"/>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
|
@ -271,7 +271,7 @@
|
|||
<Path Width="16" Height="16" Data="{StaticResource Icons.DoubleDown}" HorizontalAlignment="Center" IsVisible="{Binding Old, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||
|
||||
<Border Margin="0,8,0,0" BorderThickness="1" BorderBrush="Green" Background="{DynamicResource Brush.Window}">
|
||||
<v:CommitBaseInfo MaxHeight="256" Margin="0,0,0,4" Content="{Binding New.Commit}" Message="{Binding New.FullMessage}"/>
|
||||
<v:CommitBaseInfo MaxHeight="256" Margin="0,0,0,4" Content="{Binding New.Commit}" FullMessage="{Binding New.FullMessage}"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
</v:LayoutableGrid.ColumnDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3">
|
||||
<Grid RowDefinitions="24,*">
|
||||
<Grid RowDefinitions="24,*" Grid.IsSharedSizeScope="True">
|
||||
<!-- Headers -->
|
||||
<Border Grid.Row="0"
|
||||
Background="{DynamicResource Brush.Window}"
|
||||
|
@ -35,8 +35,8 @@
|
|||
<ColumnDefinition Width="*" MinWidth="100"/>
|
||||
<ColumnDefinition Width="3"/>
|
||||
<ColumnDefinition Width="{Binding #ThisControl.AuthorNameColumnWidth, Mode=TwoWay}" MinWidth="80"/>
|
||||
<ColumnDefinition Width="100" MaxWidth="100" MinWidth="100"/>
|
||||
<ColumnDefinition Width="170" MaxWidth="170" MinWidth="170"/>
|
||||
<ColumnDefinition SharedSizeGroup="SHA"/>
|
||||
<ColumnDefinition SharedSizeGroup="Time"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0" Classes="table_header" Text="{DynamicResource Text.Histories.Header.GraphAndSubject}" HorizontalAlignment="Center"/>
|
||||
|
@ -121,8 +121,8 @@
|
|||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="{Binding #ThisControl.AuthorNameColumnWidth, Mode=OneWay}"/>
|
||||
<ColumnDefinition Width="100" MaxWidth="100" MinWidth="100"/>
|
||||
<ColumnDefinition Width="170" MaxWidth="170" MinWidth="170"/>
|
||||
<ColumnDefinition SharedSizeGroup="SHA" Width="Auto" MinWidth="100"/>
|
||||
<ColumnDefinition SharedSizeGroup="Time" Width="Auto" MinWidth="160"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Subject & REFS -->
|
||||
|
|
|
@ -59,25 +59,39 @@
|
|||
SelectionMode="Single"
|
||||
SelectedItem="{Binding SelectedItem, Mode=OneWayToSource}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto">
|
||||
<ListBox.Styles>
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Grid.IsSharedSizeScope="True">
|
||||
<v:InteractiveRebaseListBox.Styles>
|
||||
<Style Selector="ListBoxItem">
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Height" Value="28"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
</ListBox.Styles>
|
||||
</v:InteractiveRebaseListBox.Styles>
|
||||
|
||||
<ListBox.ItemsPanel>
|
||||
<v:InteractiveRebaseListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel Orientation="Vertical"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
</v:InteractiveRebaseListBox.ItemsPanel>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<v:InteractiveRebaseListBox.ItemTemplate>
|
||||
<DataTemplate DataType="vm:InteractiveRebaseItem">
|
||||
<Grid ColumnDefinitions="16,110,*,Auto" Margin="8,0" ClipToBounds="True">
|
||||
<Grid Height="26" Margin="8,0" ClipToBounds="True">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16"/>
|
||||
<ColumnDefinition Width="110"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="32"/>
|
||||
<ColumnDefinition Width="108"/>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="CommitHashColumn"/>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="CommitTimeColumn"/>
|
||||
<ColumnDefinition Width="32"/>
|
||||
<ColumnDefinition Width="32"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Drag & Drop Anchor -->
|
||||
<Border Grid.Column="0" Background="Transparent"
|
||||
Loaded="OnSetupRowHeaderDragDrop"
|
||||
|
@ -188,47 +202,45 @@
|
|||
<TextBlock Grid.Column="1" Classes="primary" Margin="0,0,4,0" Text="{Binding Subject}"/>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Column="3" ColumnDefinitions="32,108,96,Auto,32,32" IsHitTestVisible="False" ClipToBounds="True">
|
||||
<!-- Author Avatar -->
|
||||
<v:Avatar Grid.Column="0"
|
||||
Width="16" Height="16"
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
User="{Binding Commit.Author}"/>
|
||||
<!-- Author Avatar -->
|
||||
<v:Avatar Grid.Column="3"
|
||||
Width="16" Height="16"
|
||||
Margin="8,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
User="{Binding Commit.Author}"/>
|
||||
|
||||
<!-- Author Name -->
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="primary"
|
||||
MaxWidth="90"
|
||||
Margin="6,0,12,0"
|
||||
Text="{Binding Commit.Author.Name}"
|
||||
HorizontalAlignment="Left"/>
|
||||
<!-- Author Name -->
|
||||
<Border Grid.Column="4" ClipToBounds="True">
|
||||
<TextBlock Classes="primary" Margin="6,0,12,0" Text="{Binding Commit.Author.Name}"/>
|
||||
</Border>
|
||||
|
||||
<!-- Commit SHA -->
|
||||
<Border Grid.Column="2" ClipToBounds="True">
|
||||
<TextBlock Classes="primary"
|
||||
Text="{Binding Commit.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Border>
|
||||
<!-- Commit SHA -->
|
||||
<Border Grid.Column="5" ClipToBounds="True">
|
||||
<TextBlock Classes="primary"
|
||||
Text="{Binding Commit.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Border>
|
||||
|
||||
<!-- Commit Time -->
|
||||
<Border Grid.Column="3" ClipToBounds="True">
|
||||
<TextBlock Classes="primary" Text="{Binding Commit.CommitterTimeStr}" Margin="8,0"/>
|
||||
</Border>
|
||||
<!-- Commit Time -->
|
||||
<Border Grid.Column="6">
|
||||
<TextBlock Classes="primary"
|
||||
Margin="16,0,8,0"
|
||||
Text="{Binding Commit.CommitterTimeStr}"
|
||||
HorizontalAlignment="Center"/>
|
||||
</Border>
|
||||
|
||||
<!-- MoveUp Button -->
|
||||
<Button Grid.Column="4" Classes="icon_button" Click="OnMoveItemUp" ToolTip.Tip="Alt+Up">
|
||||
<Path Width="14" Height="14" Margin="0,4,0,0" Data="{StaticResource Icons.Up}"/>
|
||||
</Button>
|
||||
<!-- MoveUp Button -->
|
||||
<Button Grid.Column="7" Classes="icon_button" Click="OnMoveItemUp" ToolTip.Tip="Alt+Up">
|
||||
<Path Width="14" Height="14" Margin="0,4,0,0" Data="{StaticResource Icons.Up}"/>
|
||||
</Button>
|
||||
|
||||
<!-- MoveDown Button -->
|
||||
<Button Grid.Column="5" Classes="icon_button" Click="OnMoveItemDown" ToolTip.Tip="Alt+Down">
|
||||
<Path Width="14" Height="14" Margin="0,4,0,0" Data="{StaticResource Icons.Down}"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
<!-- MoveDown Button -->
|
||||
<Button Grid.Column="8" Classes="icon_button" Click="OnMoveItemDown" ToolTip.Tip="Alt+Down">
|
||||
<Path Width="14" Height="14" Margin="0,4,0,0" Data="{StaticResource Icons.Down}"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</v:InteractiveRebaseListBox.ItemTemplate>
|
||||
</v:InteractiveRebaseListBox>
|
||||
|
||||
<v:LoadingIcon Grid.Row="0" Width="48" Height="48" HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="{Binding IsLoading}"/>
|
||||
|
|
|
@ -112,8 +112,19 @@ namespace SourceGit.Views
|
|||
// We should clear all unhandled key modifiers.
|
||||
_unhandledModifiers = KeyModifiers.None;
|
||||
|
||||
// Check for AltGr (which is detected as Ctrl+Alt)
|
||||
bool isAltGr = e.KeyModifiers.HasFlag(KeyModifiers.Control) &&
|
||||
e.KeyModifiers.HasFlag(KeyModifiers.Alt);
|
||||
|
||||
// Skip hotkey processing if AltGr is pressed
|
||||
if (isAltGr)
|
||||
{
|
||||
base.OnKeyDown(e);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ctrl+Shift+P opens preference dialog (macOS use hotkeys in system menu bar)
|
||||
if (!OperatingSystem.IsMacOS() && e.KeyModifiers == (KeyModifiers.Control | KeyModifiers.Shift) && e.Key == Key.P)
|
||||
if (!OperatingSystem.IsMacOS() && e is { KeyModifiers: (KeyModifiers.Control | KeyModifiers.Shift), Key: Key.P })
|
||||
{
|
||||
App.OpenDialog(new Preferences());
|
||||
e.Handled = true;
|
||||
|
@ -243,13 +254,13 @@ namespace SourceGit.Views
|
|||
{
|
||||
_unhandledModifiers = e.KeyModifiers;
|
||||
|
||||
if (!_unhandledModifiers.HasFlag(KeyModifiers.Alt) && (e.Key == Key.LeftAlt || e.Key == Key.RightAlt))
|
||||
if (!_unhandledModifiers.HasFlag(KeyModifiers.Alt) && e.Key is Key.LeftAlt or Key.RightAlt)
|
||||
_unhandledModifiers |= KeyModifiers.Alt;
|
||||
|
||||
if (!_unhandledModifiers.HasFlag(KeyModifiers.Control) && (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl))
|
||||
if (!_unhandledModifiers.HasFlag(KeyModifiers.Control) && e.Key is Key.LeftCtrl or Key.RightCtrl)
|
||||
_unhandledModifiers |= KeyModifiers.Control;
|
||||
|
||||
if (!_unhandledModifiers.HasFlag(KeyModifiers.Shift) && (e.Key == Key.LeftShift || e.Key == Key.RightShift))
|
||||
if (!_unhandledModifiers.HasFlag(KeyModifiers.Shift) && e.Key is Key.LeftShift or Key.RightShift)
|
||||
_unhandledModifiers |= KeyModifiers.Shift;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
<TabItem.Header>
|
||||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preferences.Appearance}"/>
|
||||
</TabItem.Header>
|
||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
|
||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preferences.Appearance.Theme}"
|
||||
HorizontalAlignment="Right"
|
||||
|
@ -190,12 +190,12 @@
|
|||
Margin="0,0,16,0"/>
|
||||
<Grid Grid.Row="3" Grid.Column="1" ColumnDefinitions="*,8,*">
|
||||
<NumericUpDown Grid.Column="0"
|
||||
Minimum="10" Maximum="18" Increment="0.5"
|
||||
Height="28"
|
||||
Padding="4"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
|
||||
CornerRadius="3"
|
||||
Value="{Binding DefaultFontSize, Mode=TwoWay}">
|
||||
Minimum="10" Maximum="18" Increment="0.5"
|
||||
Height="28"
|
||||
Padding="4"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
|
||||
CornerRadius="3"
|
||||
Value="{Binding DefaultFontSize, Mode=TwoWay}">
|
||||
<NumericUpDown.InnerLeftContent>
|
||||
<Border BorderThickness="0,0,1,0" BorderBrush="{DynamicResource Brush.Border1}">
|
||||
<TextBlock Margin="4,0" Text="{DynamicResource Text.Preferences.Appearance.FontSize.Default}"/>
|
||||
|
@ -218,10 +218,23 @@
|
|||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preferences.Appearance.EditorTabWidth}"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,16,0"/>
|
||||
<Grid Grid.Row="4" Grid.Column="1">
|
||||
<NumericUpDown Minimum="1" Maximum="16" Increment="1"
|
||||
Height="28"
|
||||
Padding="4"
|
||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
|
||||
CornerRadius="3"
|
||||
Value="{Binding EditorTabWidth, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="0"
|
||||
Text="{DynamicResource Text.Preferences.Appearance.ThemeOverrides}"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,16,0"/>
|
||||
<TextBox Grid.Row="4" Grid.Column="1"
|
||||
<TextBox Grid.Row="5" Grid.Column="1"
|
||||
Height="28"
|
||||
CornerRadius="3"
|
||||
Text="{Binding ThemeOverrides, Mode=TwoWay}">
|
||||
|
@ -232,16 +245,16 @@
|
|||
</TextBox.InnerRightContent>
|
||||
</TextBox>
|
||||
|
||||
<CheckBox Grid.Row="5" Grid.Column="1"
|
||||
<CheckBox Grid.Row="6" Grid.Column="1"
|
||||
Content="{DynamicResource Text.Preferences.Appearance.OnlyUseMonoFontInEditor}"
|
||||
IsChecked="{Binding OnlyUseMonoFontInEditor, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="6" Grid.Column="1"
|
||||
<CheckBox Grid.Row="7" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.Appearance.UseFixedTabWidth}"
|
||||
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseFixedTabWidth, Mode=TwoWay}"/>
|
||||
|
||||
<CheckBox Grid.Row="7" Grid.Column="1"
|
||||
<CheckBox Grid.Row="8" Grid.Column="1"
|
||||
Height="32"
|
||||
Content="{DynamicResource Text.Preferences.Appearance.UseNativeWindowFrame}"
|
||||
IsChecked="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSystemWindowFrame, Mode=OneTime}"
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<DataTemplate DataType="m:RevisionTextFile">
|
||||
<v:RevisionTextFileView FontFamily="{DynamicResource Fonts.Monospace}"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
|
||||
TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
|
||||
Background="{DynamicResource Brush.Contents}"/>
|
||||
</DataTemplate>
|
||||
|
||||
|
@ -63,7 +64,7 @@
|
|||
<Grid RowDefinitions="Auto,*" Margin="8,0">
|
||||
<TextBlock Grid.Row="0" Margin="0,8,0,0" Text="{DynamicResource Text.CommitDetail.Files.Submodule}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
|
||||
<ScrollViewer Grid.Row="1" Margin="0,16,0,0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||
<v:CommitBaseInfo Content="{Binding Commit}" Message="{Binding FullMessage}"/>
|
||||
<v:CommitBaseInfo Content="{Binding Commit}" FullMessage="{Binding FullMessage}"/>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
|
|
@ -15,6 +15,15 @@ namespace SourceGit.Views
|
|||
{
|
||||
public class RevisionTextFileView : TextEditor
|
||||
{
|
||||
public static readonly StyledProperty<int> TabWidthProperty =
|
||||
AvaloniaProperty.Register<RevisionTextFileView, int>(nameof(TabWidth), 4);
|
||||
|
||||
public int TabWidth
|
||||
{
|
||||
get => GetValue(TabWidthProperty);
|
||||
set => SetValue(TabWidthProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||
|
||||
public RevisionTextFileView() : base(new TextArea(), new TextDocument())
|
||||
|
@ -22,13 +31,16 @@ namespace SourceGit.Views
|
|||
IsReadOnly = true;
|
||||
ShowLineNumbers = true;
|
||||
WordWrap = false;
|
||||
|
||||
Options.IndentationSize = TabWidth;
|
||||
Options.EnableHyperlinks = false;
|
||||
Options.EnableEmailHyperlinks = false;
|
||||
|
||||
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
|
||||
TextArea.LeftMargins[0].Margin = new Thickness(8, 0);
|
||||
TextArea.TextView.Margin = new Thickness(4, 0);
|
||||
TextArea.TextView.Options.EnableHyperlinks = false;
|
||||
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
|
@ -69,6 +81,16 @@ namespace SourceGit.Views
|
|||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == TabWidthProperty)
|
||||
{
|
||||
Options.IndentationSize = TabWidth;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
var selected = SelectedText;
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<Popup PlacementTarget="{Binding #TxtSearchRevisionFiles}"
|
||||
Placement="BottomEdgeAlignedLeft"
|
||||
HorizontalOffset="-8" VerticalAlignment="-8"
|
||||
IsOpen="{Binding IsRevisionFileSearchSuggestionOpen}">
|
||||
IsOpen="{Binding RevisionFileSearchSuggestion, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}">
|
||||
<Border Margin="8" VerticalAlignment="Top" Effect="drop-shadow(0 0 8 #80000000)">
|
||||
<Border Background="{DynamicResource Brush.Popup}" CornerRadius="4" Padding="4" BorderThickness="0.65" BorderBrush="{DynamicResource Brush.Accent}">
|
||||
<ListBox x:Name="SearchSuggestionBox"
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
else if (e.Key == Key.Down || e.Key == Key.Up)
|
||||
{
|
||||
if (vm.IsRevisionFileSearchSuggestionOpen)
|
||||
if (vm.RevisionFileSearchSuggestion.Count > 0)
|
||||
{
|
||||
SearchSuggestionBox.Focus(NavigationMethod.Tab);
|
||||
SearchSuggestionBox.SelectedIndex = 0;
|
||||
|
@ -33,12 +33,7 @@ namespace SourceGit.Views
|
|||
}
|
||||
else if (e.Key == Key.Escape)
|
||||
{
|
||||
if (vm.IsRevisionFileSearchSuggestionOpen)
|
||||
{
|
||||
vm.RevisionFileSearchSuggestion.Clear();
|
||||
vm.IsRevisionFileSearchSuggestionOpen = false;
|
||||
}
|
||||
|
||||
vm.CancelRevisionFileSuggestions();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +52,7 @@ namespace SourceGit.Views
|
|||
|
||||
if (e.Key == Key.Escape)
|
||||
{
|
||||
vm.RevisionFileSearchSuggestion.Clear();
|
||||
vm.CancelRevisionFileSuggestions();
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Enter && SearchSuggestionBox.SelectedItem is string content)
|
||||
|
|
|
@ -9,18 +9,14 @@ namespace SourceGit.Views
|
|||
{
|
||||
public StandaloneCommitMessageEditor()
|
||||
{
|
||||
_file = string.Empty;
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public StandaloneCommitMessageEditor(string file)
|
||||
public void SetFile(string file)
|
||||
{
|
||||
_file = file;
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
|
||||
var content = File.ReadAllText(file).ReplaceLineEndings("\n");
|
||||
var content = File.ReadAllText(file).ReplaceLineEndings("\n").Trim();
|
||||
var firstLineEnd = content.IndexOf('\n');
|
||||
if (firstLineEnd == -1)
|
||||
{
|
||||
|
@ -29,7 +25,7 @@ namespace SourceGit.Views
|
|||
else
|
||||
{
|
||||
Editor.SubjectEditor.Text = content.Substring(0, firstLineEnd);
|
||||
Editor.DescriptionEditor.Text = content.Substring(firstLineEnd + 1);
|
||||
Editor.DescriptionEditor.Text = content.Substring(firstLineEnd + 1).Trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,12 +37,16 @@ namespace SourceGit.Views
|
|||
|
||||
private void SaveAndClose(object _1, RoutedEventArgs _2)
|
||||
{
|
||||
File.WriteAllText(_file, Editor.Text);
|
||||
_exitCode = 0;
|
||||
if (!string.IsNullOrEmpty(_file))
|
||||
{
|
||||
File.WriteAllText(_file, Editor.Text);
|
||||
_exitCode = 0;
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
private readonly string _file;
|
||||
private string _file = string.Empty;
|
||||
private int _exitCode = -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||
FontFamily="{DynamicResource Fonts.Monospace}"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
|
||||
TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="{Binding Source={x:Static vm:Preferences.Instance}, Path=EnableDiffViewWordWrap}"
|
||||
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
|
||||
|
@ -59,6 +60,7 @@
|
|||
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||
FontFamily="{DynamicResource Fonts.Monospace}"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
|
||||
TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="False"
|
||||
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
|
||||
|
@ -81,6 +83,7 @@
|
|||
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||
FontFamily="{DynamicResource Fonts.Monospace}"
|
||||
FontSize="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorFontSize}"
|
||||
TabWidth="{Binding Source={x:Static vm:Preferences.Instance}, Path=EditorTabWidth}"
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preferences.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="False"
|
||||
ShowHiddenSymbols="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowHiddenSymbolsInDiffView}"
|
||||
|
|
|
@ -60,7 +60,7 @@ namespace SourceGit.Views
|
|||
|
||||
public class ThemedTextDiffPresenter : TextEditor
|
||||
{
|
||||
public class VerticalSeperatorMargin : AbstractMargin
|
||||
public class VerticalSeparatorMargin : AbstractMargin
|
||||
{
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
|
@ -475,6 +475,15 @@ namespace SourceGit.Views
|
|||
set => SetValue(ShowHiddenSymbolsProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<int> TabWidthProperty =
|
||||
AvaloniaProperty.Register<ThemedTextDiffPresenter, int>(nameof(TabWidth), 4);
|
||||
|
||||
public int TabWidth
|
||||
{
|
||||
get => GetValue(TabWidthProperty);
|
||||
set => SetValue(TabWidthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> EnableChunkSelectionProperty =
|
||||
AvaloniaProperty.Register<ThemedTextDiffPresenter, bool>(nameof(EnableChunkSelection));
|
||||
|
||||
|
@ -519,12 +528,13 @@ namespace SourceGit.Views
|
|||
ShowLineNumbers = false;
|
||||
BorderThickness = new Thickness(0);
|
||||
|
||||
Options.IndentationSize = TabWidth;
|
||||
Options.EnableHyperlinks = false;
|
||||
Options.EnableEmailHyperlinks = false;
|
||||
|
||||
_lineStyleTransformer = new LineStyleTransformer(this);
|
||||
|
||||
TextArea.TextView.Margin = new Thickness(2, 0);
|
||||
TextArea.TextView.Options.EnableHyperlinks = false;
|
||||
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
||||
|
||||
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
|
||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||
}
|
||||
|
@ -734,10 +744,14 @@ namespace SourceGit.Views
|
|||
}
|
||||
else if (change.Property == ShowHiddenSymbolsProperty)
|
||||
{
|
||||
var val = change.NewValue is true;
|
||||
var val = ShowHiddenSymbols;
|
||||
Options.ShowTabs = val;
|
||||
Options.ShowSpaces = val;
|
||||
}
|
||||
else if (change.Property == TabWidthProperty)
|
||||
{
|
||||
Options.IndentationSize = TabWidth;
|
||||
}
|
||||
else if (change.Property == FileNameProperty)
|
||||
{
|
||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName);
|
||||
|
@ -1007,8 +1021,8 @@ namespace SourceGit.Views
|
|||
if (startPosition.Location > endPosition.Location)
|
||||
(startPosition, endPosition) = (endPosition, startPosition);
|
||||
|
||||
var startIdx = Math.Min(startPosition.Line - 1, lines.Count - 1);
|
||||
var endIdx = Math.Min(endPosition.Line - 1, lines.Count - 1);
|
||||
var startIdx = startPosition.Line - 1;
|
||||
var endIdx = endPosition.Line - 1;
|
||||
|
||||
if (startIdx == endIdx)
|
||||
{
|
||||
|
@ -1025,25 +1039,35 @@ namespace SourceGit.Views
|
|||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
for (var i = startIdx; i <= endIdx; i++)
|
||||
for (var i = startIdx; i <= endIdx && i <= lines.Count - 1; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (line.Type == Models.TextDiffLineType.Indicator ||
|
||||
line.Type == Models.TextDiffLineType.None)
|
||||
continue;
|
||||
|
||||
// The first selected line (partial selection)
|
||||
if (i == startIdx && startPosition.Column > 1)
|
||||
{
|
||||
builder.AppendLine(line.Content.Substring(startPosition.Column - 1));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == endIdx && endPosition.Column < line.Content.Length)
|
||||
// The selection range is larger than original source.
|
||||
if (i == lines.Count - 1 && i < endIdx)
|
||||
{
|
||||
builder.AppendLine(line.Content.Substring(0, endPosition.Column));
|
||||
continue;
|
||||
builder.Append(line.Content);
|
||||
break;
|
||||
}
|
||||
|
||||
// For the last line (selection range is within original source)
|
||||
if (i == endIdx)
|
||||
{
|
||||
builder.Append(endPosition.Column - 1 < line.Content.Length ? line.Content.Substring(0, endPosition.Column - 1) : line.Content);
|
||||
break;
|
||||
}
|
||||
|
||||
// Other lines.
|
||||
builder.AppendLine(line.Content);
|
||||
}
|
||||
|
||||
|
@ -1061,9 +1085,9 @@ namespace SourceGit.Views
|
|||
public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument())
|
||||
{
|
||||
TextArea.LeftMargins.Add(new LineNumberMargin(false, true));
|
||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin());
|
||||
TextArea.LeftMargins.Add(new VerticalSeparatorMargin());
|
||||
TextArea.LeftMargins.Add(new LineNumberMargin(false, false));
|
||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin());
|
||||
TextArea.LeftMargins.Add(new VerticalSeparatorMargin());
|
||||
TextArea.LeftMargins.Add(new LineModifyTypeMargin());
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1286,7 @@ namespace SourceGit.Views
|
|||
public SingleSideTextDiffPresenter() : base(new TextArea(), new TextDocument())
|
||||
{
|
||||
TextArea.LeftMargins.Add(new LineNumberMargin(true, false));
|
||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin());
|
||||
TextArea.LeftMargins.Add(new VerticalSeparatorMargin());
|
||||
TextArea.LeftMargins.Add(new LineModifyTypeMargin());
|
||||
}
|
||||
|
||||
|
|
|
@ -211,7 +211,12 @@
|
|||
<StackPanel Orientation="Horizontal">
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Branch}"/>
|
||||
<TextBlock Margin="4,0,0,0" Text="{Binding FriendlyName}"/>
|
||||
<TextBlock Margin="4,0,0,0" Text="{Binding Head, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
||||
<TextBlock Margin="4,0,0,0"
|
||||
Text="{Binding Head, Converter={x:Static c:StringConverters.ToShortSHA}}"
|
||||
Foreground="DarkOrange"
|
||||
TextDecorations="Underline"
|
||||
Cursor="Hand"
|
||||
PointerPressed="OnPressedSHA"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
|
@ -225,18 +230,15 @@
|
|||
FontSize="11"
|
||||
VerticalAlignment="Center"
|
||||
UseGraphColor="False"/>
|
||||
<TextBlock Margin="4,0,0,0" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
||||
<TextBlock Margin="4,0,0,0"
|
||||
Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
|
||||
Foreground="DarkOrange"
|
||||
TextDecorations="Underline"
|
||||
Cursor="Hand"
|
||||
PointerPressed="OnPressedSHA"/>
|
||||
<TextBlock Margin="4,0,0,0" Text="{Binding Subject}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="m:Tag">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Tag}"/>
|
||||
<TextBlock Margin="4,0,0,0" Text="{Binding Name}"/>
|
||||
<TextBlock Margin="4,0,0,0" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</StackPanel.DataTemplates>
|
||||
|
||||
<Path Width="64" Height="64" Data="{StaticResource Icons.Conflict}" Fill="{DynamicResource Brush.FG2}" HorizontalAlignment="Center"/>
|
||||
|
@ -397,7 +399,8 @@
|
|||
Width="0" Height="0"
|
||||
Background="Transparent"
|
||||
Command="{Binding CommitWithAutoStage}"
|
||||
HotKey="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"/>
|
||||
HotKey="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"
|
||||
IsEnabled="{Binding !IsCommitting}"/>
|
||||
|
||||
<Button Grid.Column="8"
|
||||
Classes="flat"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
|
@ -159,5 +160,14 @@ namespace SourceGit.Views
|
|||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPressedSHA(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
var repoView = this.FindAncestorOfType<Repository>();
|
||||
if (repoView is { DataContext: ViewModels.Repository repo } && sender is TextBlock text)
|
||||
repo.NavigateToCommit(text.Text);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue