Merge branch 'release/8.27'

This commit is contained in:
leo 2024-08-26 10:19:14 +08:00
commit cead68145a
No known key found for this signature in database
104 changed files with 3230 additions and 1880 deletions

68
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,68 @@
name: Build
on:
workflow_call:
jobs:
build:
strategy:
matrix:
include:
- name : Windows x64
os: windows-2019
runtime: win-x64
- name : Windows ARM64
os: windows-2019
runtime: win-arm64
- name : macOS (Intel)
os: macos-13
runtime: osx-x64
- name : macOS (Apple Silicon)
os: macos-latest
runtime: osx-arm64
- name : Linux
os: ubuntu-20.04
runtime: linux-x64
- name : Linux (arm64)
os: ubuntu-20.04
runtime: linux-arm64
name: Build ${{ matrix.name }}
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Configure arm64 packages
if: ${{ matrix.runtime == 'linux-arm64' }}
run: |
sudo dpkg --add-architecture arm64
echo 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ focal main restricted
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted' \
| sudo tee /etc/apt/sources.list.d/arm64.list
sudo sed -i -e 's/^deb http/deb [arch=amd64] http/g' /etc/apt/sources.list
sudo sed -i -e 's/^deb mirror/deb [arch=amd64] mirror/g' /etc/apt/sources.list
- name: Install cross-compiling dependencies
if: ${{ matrix.runtime == 'linux-arm64' }}
run: |
sudo apt-get update
sudo apt-get install clang llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64
- name: Build
run: dotnet build -c Release
- name: Publish
run: dotnet publish src/SourceGit.csproj -c Release -o publish -r ${{ matrix.runtime }}
- name: Rename executable file
if: ${{ startsWith(matrix.runtime, 'linux-') }}
run: mv publish/SourceGit publish/sourcegit
- name: Tar artifact
if: ${{ startsWith(matrix.runtime, 'linux-') || startsWith(matrix.runtime, 'osx-') }}
run: |
tar -cvf "sourcegit.${{ matrix.runtime }}.tar" -C publish .
rm -r publish/*
mv "sourcegit.${{ matrix.runtime }}.tar" publish
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sourcegit.${{ matrix.runtime }}
path: publish/*

View file

@ -8,66 +8,22 @@ on:
workflow_call:
jobs:
build:
strategy:
matrix:
include:
- name : Windows x64
os: windows-2019
runtime: win-x64
- name : Windows ARM64
os: windows-2019
runtime: win-arm64
- name : macOS (Intel)
os: macos-13
runtime: osx-x64
- name : macOS (Apple Silicon)
os: macos-latest
runtime: osx-arm64
- name : Linux
os: ubuntu-20.04
runtime: linux-x64
- name : Linux (arm64)
os: ubuntu-20.04
runtime: linux-arm64
name: Build ${{ matrix.name }}
runs-on: ${{ matrix.os }}
name: Build
uses: ./.github/workflows/build.yml
version:
name: Prepare version string
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
- name: Output version string
id: version
run: echo "version=$(cat VERSION)" >> "$GITHUB_OUTPUT"
package:
needs: [build, version]
name: Package
uses: ./.github/workflows/package.yml
with:
dotnet-version: 8.0.x
- name: Configure arm64 packages
if: ${{ matrix.runtime == 'linux-arm64' }}
run: |
sudo dpkg --add-architecture arm64
echo 'deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ focal main restricted
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted' \
| sudo tee /etc/apt/sources.list.d/arm64.list
sudo sed -i -e 's/^deb http/deb [arch=amd64] http/g' /etc/apt/sources.list
sudo sed -i -e 's/^deb mirror/deb [arch=amd64] mirror/g' /etc/apt/sources.list
- name: Install cross-compiling dependencies
if: ${{ matrix.runtime == 'linux-arm64' }}
run: |
sudo apt-get update
sudo apt-get install clang llvm gcc-aarch64-linux-gnu zlib1g-dev:arm64
- name: Build
run: dotnet build -c Release
- name: Publish
run: dotnet publish src/SourceGit.csproj -c Release -o publish -r ${{ matrix.runtime }}
- name: Rename executable file
if: ${{ startsWith(matrix.runtime, 'linux-') }}
run: mv publish/SourceGit publish/sourcegit
- name: Tar artifact
if: ${{ startsWith(matrix.runtime, 'linux-') }}
run: |
tar -cvf "sourcegit.${{ matrix.runtime }}.tar" -C publish .
rm -r publish/*
mv "sourcegit.${{ matrix.runtime }}.tar" publish
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sourcegit.${{ matrix.runtime }}
path: publish
version: ${{ needs.version.outputs.version }}

View file

@ -7,12 +7,8 @@ on:
required: true
type: string
jobs:
build:
name: Build
uses: ./.github/workflows/ci.yml
windows-portable:
name: Package portable Windows app
needs: build
runs-on: ubuntu-latest
strategy:
matrix:
@ -35,10 +31,13 @@ jobs:
with:
name: package.${{ matrix.runtime }}
path: build/sourcegit_*.zip
- name: Delete temp artifacts
uses: geekyeggo/delete-artifact@v5
with:
name: sourcegit.${{ matrix.runtime }}
osx-app:
name: Package OSX app
needs: build
runs-on: ubuntu-latest
runs-on: macos-latest
strategy:
matrix:
runtime: [osx-x64, osx-arm64]
@ -49,20 +48,26 @@ jobs:
uses: actions/download-artifact@v4
with:
name: sourcegit.${{ matrix.runtime }}
path: build/SourceGit
path: build
- name: Package
env:
VERSION: ${{ inputs.version }}
RUNTIME: ${{ matrix.runtime }}
run: ./build/scripts/package.osx-app.sh
run: |
mkdir build/SourceGit
tar -xf "build/sourcegit.${{ matrix.runtime }}.tar" -C build/SourceGit
./build/scripts/package.osx-app.sh
- name: Upload package artifact
uses: actions/upload-artifact@v4
with:
name: package.${{ matrix.runtime }}
path: build/sourcegit_*.zip
- name: Delete temp artifacts
uses: geekyeggo/delete-artifact@v5
with:
name: sourcegit.${{ matrix.runtime }}
linux:
name: Package Linux
needs: build
runs-on: ubuntu-latest
strategy:
matrix:
@ -96,3 +101,7 @@ jobs:
build/sourcegit-*.AppImage
build/sourcegit_*.deb
build/sourcegit-*.rpm
- name: Delete temp artifacts
uses: geekyeggo/delete-artifact@v5
with:
name: sourcegit.${{ matrix.runtime }}

View file

@ -4,6 +4,9 @@ on:
tags:
- v*
jobs:
build:
name: Build
uses: ./.github/workflows/build.yml
version:
name: Prepare version string
runs-on: ubuntu-latest
@ -16,13 +19,13 @@ jobs:
TAG: ${{ github.ref_name }}
run: echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
package:
needs: version
needs: [build, version]
name: Package
uses: ./.github/workflows/package.yml
with:
version: ${{ needs.version.outputs.version }}
release:
needs: [version, package]
needs: [package, version]
name: Release
runs-on: ubuntu-latest
permissions:
@ -34,7 +37,8 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
run: gh release create "$TAG" -t "Release ${TAG#v}" --notes-from-tag
VERSION: ${{ needs.version.outputs.version }}
run: gh release create "$TAG" -t "Release $VERSION" --notes-from-tag
- name: Download artifacts
uses: actions/download-artifact@v4
with:
@ -45,5 +49,4 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
VERSION: ${{ needs.version.outputs.version }}
run: gh release upload "$TAG" packages/*

View file

@ -83,7 +83,6 @@ For **Linux** users:
* `xdg-open` must be installed to support open native file manager.
* Make sure [git-credential-manager](https://github.com/git-ecosystem/git-credential-manager/releases) is installed on your linux.
* Maybe you need to set environment variable `AVALONIA_SCREEN_SCALE_FACTORS`. See https://github.com/AvaloniaUI/Avalonia/wiki/Configuring-X11-per-monitor-DPI.
## External Tools
@ -123,7 +122,7 @@ This app supports open repository in external tools listed in the table below.
* Custom
You can find custom themes from [sourcegit-theme](https://github.com/sourcegit-scm/sourcegit-theme.git)
You can find custom themes from [sourcegit-theme](https://github.com/sourcegit-scm/sourcegit-theme.git). And welcome to share your own themes.
## Contributing

View file

@ -1 +1 @@
8.26
8.27

View file

@ -5,8 +5,8 @@ Summary: Open-source & Free Git Gui Client
License: MIT
URL: https://sourcegit-scm.github.io/
Source: https://github.com/sourcegit-scm/sourcegit/archive/refs/tags/v%_version.tar.gz
Requires: libX11.so.6
Requires: libSM.so.6
Requires: libX11
Requires: libSM
%define _build_id_links none
@ -19,7 +19,7 @@ mkdir -p %{buildroot}/%{_bindir}
mkdir -p %{buildroot}/usr/share/applications
mkdir -p %{buildroot}/usr/share/icons
cp -f ../../../SourceGit/* %{buildroot}/opt/sourcegit/
ln -sf ../../opt/sourcegit/sourcegit %{buildroot}/%{_bindir}
ln -rsf %{buildroot}/opt/sourcegit/sourcegit %{buildroot}/%{_bindir}
cp -r ../../_common/applications %{buildroot}/%{_datadir}
cp -r ../../_common/icons %{buildroot}/%{_datadir}
chmod 755 -R %{buildroot}/opt/sourcegit

View file

@ -60,7 +60,7 @@ mkdir -p resources/deb/usr/bin
mkdir -p resources/deb/usr/share/applications
mkdir -p resources/deb/usr/share/icons
cp -f SourceGit/* resources/deb/opt/sourcegit
ln -sf ../../opt/sourcegit/sourcegit resources/deb/usr/bin
ln -rsf resources/deb/opt/sourcegit/sourcegit resources/deb/usr/bin
cp -r resources/_common/applications resources/deb/usr/share
cp -r resources/_common/icons resources/deb/usr/share
sed -i -e "s/^Version:.*/Version: $VERSION/" -e "s/^Architecture:.*/Architecture: $arch/" resources/deb/DEBIAN/control

View file

@ -18,5 +18,6 @@ mkdir -p SourceGit.app/Contents/Resources
mv SourceGit SourceGit.app/Contents/MacOS
cp resources/app/App.icns SourceGit.app/Contents/Resources/App.icns
sed "s/SOURCE_GIT_VERSION/$VERSION/g" resources/app/App.plist > SourceGit.app/Contents/Info.plist
rm -rf SourceGit.app/Contents/MacOS/SourceGit.dsym
zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit.app -x "*/*\.dsym/*"
zip "sourcegit_$VERSION.$RUNTIME.zip" -r SourceGit.app

65
src/App.Commands.cs Normal file
View file

@ -0,0 +1,65 @@
using System;
using System.Windows.Input;
using Avalonia.Controls;
namespace SourceGit
{
public partial class App
{
public class SimpleCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
public SimpleCommand(Action action)
{
_action = action;
}
public bool CanExecute(object parameter) => _action != null;
public void Execute(object parameter) => _action?.Invoke();
private Action _action = null;
}
public class ParameterCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
public ParameterCommand(Action<object> action)
{
_action = action;
}
public bool CanExecute(object parameter) => _action != null;
public void Execute(object parameter) => _action?.Invoke(parameter);
private Action<object> _action = null;
}
public static readonly SimpleCommand OpenPreferenceCommand = new SimpleCommand(() => OpenDialog(new Views.Preference()));
public static readonly SimpleCommand OpenHotkeysCommand = new SimpleCommand(() => OpenDialog(new Views.Hotkeys()));
public static readonly SimpleCommand OpenAppDataDirCommand = new SimpleCommand(() => Native.OS.OpenInFileManager(Native.OS.DataDir));
public static readonly SimpleCommand OpenAboutCommand = new SimpleCommand(() => OpenDialog(new Views.About()));
public static readonly SimpleCommand CheckForUpdateCommand = new SimpleCommand(() => Check4Update(true));
public static readonly SimpleCommand QuitCommand = new SimpleCommand(() => Quit(0));
public static readonly ParameterCommand CopyTextCommand = new ParameterCommand(param =>
{
if (param is TextBlock textBlock)
{
if (textBlock.Inlines is { Count: > 0 } inlines)
CopyText(inlines.Text);
else
CopyText(textBlock.Text);
}
});
}
}

View file

@ -20,20 +20,6 @@ namespace SourceGit
}
}
public class FontFamilyConverter : JsonConverter<FontFamily>
{
public override FontFamily Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var name = reader.GetString();
return new FontFamily(name);
}
public override void Write(Utf8JsonWriter writer, FontFamily value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
public class GridLengthConverter : JsonConverter<GridLength>
{
public override GridLength Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
@ -54,7 +40,6 @@ namespace SourceGit
IgnoreReadOnlyProperties = true,
Converters = [
typeof(ColorConverter),
typeof(FontFamilyConverter),
typeof(GridLengthConverter),
]
)]

View file

@ -13,6 +13,7 @@
<ResourceInclude x:Key="de_DE" Source="/Resources/Locales/de_DE.axaml"/>
<ResourceInclude x:Key="en_US" Source="/Resources/Locales/en_US.axaml"/>
<ResourceInclude x:Key="fr_FR" Source="/Resources/Locales/fr_FR.axaml"/>
<ResourceInclude x:Key="pt_BR" Source="/Resources/Locales/pt_BR.axaml"/>
<ResourceInclude x:Key="zh_CN" Source="/Resources/Locales/zh_CN.axaml"/>
<ResourceInclude x:Key="zh_TW" Source="/Resources/Locales/zh_TW.axaml"/>

View file

@ -6,7 +6,6 @@ using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
@ -15,30 +14,12 @@ using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Fonts;
using Avalonia.Platform.Storage;
using Avalonia.Styling;
using Avalonia.Threading;
namespace SourceGit
{
public class SimpleCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { }
remove { }
}
public SimpleCommand(Action action)
{
_action = action;
}
public bool CanExecute(object parameter) => _action != null;
public void Execute(object parameter) => _action?.Invoke();
private Action _action = null;
}
public partial class App : Application
{
[STAThread]
@ -89,47 +70,37 @@ namespace SourceGit
return builder;
}
public static readonly SimpleCommand OpenPreferenceCommand = new SimpleCommand(() =>
public override void Initialize()
{
var toplevel = GetTopLevel() as Window;
if (toplevel == null)
AvaloniaXamlLoader.Load(this);
var pref = ViewModels.Preference.Instance;
SetLocale(pref.Locale);
SetTheme(pref.Theme, pref.ThemeOverrides);
SetFonts(pref.DefaultFontFamily, pref.MonospaceFontFamily, pref.OnlyUseMonoFontInEditor);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
BindingPlugins.DataValidators.RemoveAt(0);
if (TryLaunchedAsCoreEditor(desktop))
return;
var dialog = new Views.Preference();
dialog.ShowDialog(toplevel);
});
public static readonly SimpleCommand OpenHotkeysCommand = new SimpleCommand(() =>
{
var toplevel = GetTopLevel() as Window;
if (toplevel == null)
if (TryLaunchedAsAskpass(desktop))
return;
var dialog = new Views.Hotkeys();
dialog.ShowDialog(toplevel);
});
TryLaunchedAsNormal(desktop);
}
}
public static readonly SimpleCommand OpenAppDataDirCommand = new SimpleCommand(() =>
public static void OpenDialog(Window window)
{
Native.OS.OpenInFileManager(Native.OS.DataDir);
});
public static readonly SimpleCommand OpenAboutCommand = new SimpleCommand(() =>
{
var toplevel = GetTopLevel() as Window;
if (toplevel == null)
return;
var dialog = new Views.About();
dialog.ShowDialog(toplevel);
});
public static readonly SimpleCommand CheckForUpdateCommand = new SimpleCommand(() =>
{
Check4Update(true);
});
public static readonly SimpleCommand QuitCommand = new SimpleCommand(() => Quit(0));
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner})
window.ShowDialog(owner);
}
public static void RaiseException(string context, string message)
{
@ -146,7 +117,10 @@ namespace SourceGit
public static void SetLocale(string localeKey)
{
var app = Current as App;
var targetLocale = app?.Resources[localeKey] as ResourceDictionary;
if (app == null)
return;
var targetLocale = app.Resources[localeKey] as ResourceDictionary;
if (targetLocale == null || targetLocale == app._activeLocale)
return;
@ -211,12 +185,55 @@ namespace SourceGit
}
}
public static void SetFonts(string defaultFont, string monospaceFont, bool onlyUseMonospaceFontInEditor)
{
var app = Current as App;
if (app == null)
return;
if (app._fontsOverrides != null)
{
app.Resources.MergedDictionaries.Remove(app._fontsOverrides);
app._fontsOverrides = null;
}
var resDic = new ResourceDictionary();
if (!string.IsNullOrEmpty(defaultFont))
resDic.Add("Fonts.Default", new FontFamily(defaultFont));
if (string.IsNullOrEmpty(monospaceFont))
{
if (!string.IsNullOrEmpty(defaultFont))
{
monospaceFont = $"fonts:SourceGit#JetBrains Mono,{defaultFont}";
resDic.Add("Fonts.Monospace", new FontFamily(monospaceFont));
}
}
else
{
if (!string.IsNullOrEmpty(defaultFont) && !monospaceFont.Contains(defaultFont, StringComparison.Ordinal))
monospaceFont = $"{monospaceFont},{defaultFont}";
resDic.Add("Fonts.Monospace", new FontFamily(monospaceFont));
}
var primary = onlyUseMonospaceFontInEditor ? defaultFont : monospaceFont;
if (!string.IsNullOrEmpty(primary))
resDic.Add("Fonts.Primary", new FontFamily(primary));
if (resDic.Count > 0)
{
app.Resources.MergedDictionaries.Add(resDic);
app._fontsOverrides = resDic;
}
}
public static async void CopyText(string data)
{
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
if (desktop.MainWindow?.Clipboard is { } clipboard)
await clipboard.SetTextAsync(data);
await clipboard.SetTextAsync(data ?? "");
}
}
@ -258,17 +275,74 @@ namespace SourceGit
return icon;
}
public static TopLevel GetTopLevel()
public static IStorageProvider GetStorageProvider()
{
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
return desktop.MainWindow?.StorageProvider;
return null;
}
public static ViewModels.Launcher GetLauncer()
{
return desktop.MainWindow;
return Current is App app ? app._launcher : null;
}
public static ViewModels.Repository FindOpenedRepository(string repoPath)
{
if (Current is App app && app._launcher != null)
{
foreach (var page in app._launcher.Pages)
{
var id = page.Node.Id.Replace("\\", "/");
if (id == repoPath && page.Data is ViewModels.Repository repo)
return repo;
}
}
return null;
}
public static void Check4Update(bool manually = false)
public static void Quit(int exitCode)
{
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow?.Close();
desktop.Shutdown(exitCode);
}
else
{
Environment.Exit(exitCode);
}
}
private static void LogException(Exception ex)
{
if (ex == null)
return;
var builder = new StringBuilder();
builder.Append($"Crash::: {ex.GetType().FullName}: {ex.Message}\n\n");
builder.Append("----------------------------\n");
builder.Append($"Version: {Assembly.GetExecutingAssembly().GetName().Version}\n");
builder.Append($"OS: {Environment.OSVersion.ToString()}\n");
builder.Append($"Framework: {AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName}\n");
builder.Append($"Source: {ex.Source}\n");
builder.Append($"---------------------------\n\n");
builder.Append(ex.StackTrace);
while (ex.InnerException != null)
{
ex = ex.InnerException;
builder.Append($"\n\nInnerException::: {ex.GetType().FullName}: {ex.Message}\n");
builder.Append(ex.StackTrace);
}
var time = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
var file = Path.Combine(Native.OS.DataDir, $"crash_{time}.log");
File.WriteAllText(file, builder.ToString());
}
private static void Check4Update(bool manually = false)
{
Task.Run(async () =>
{
@ -309,104 +383,11 @@ namespace SourceGit
});
}
public static ViewModels.Launcher GetLauncer()
{
return Current is App app ? app._launcher : null;
}
public static ViewModels.Repository FindOpenedRepository(string repoPath)
{
if (Current is App app && app._launcher != null)
{
foreach (var page in app._launcher.Pages)
{
var id = page.Node.Id.Replace("\\", "/");
if (id == repoPath && page.Data is ViewModels.Repository repo)
return repo;
}
}
return null;
}
public static void Quit(int exitCode)
{
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow?.Close();
desktop.Shutdown(exitCode);
}
else
{
Environment.Exit(exitCode);
}
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
var pref = ViewModels.Preference.Instance;
SetLocale(pref.Locale);
SetTheme(pref.Theme, pref.ThemeOverrides);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
BindingPlugins.DataValidators.RemoveAt(0);
if (TryLaunchedAsCoreEditor(desktop))
return;
if (TryLaunchedAsAskpass(desktop))
return;
TryLaunchedAsNormal(desktop);
}
}
private static void LogException(Exception ex)
{
if (ex == null)
return;
var builder = new StringBuilder();
builder.Append($"Crash::: {ex.GetType().FullName}: {ex.Message}\n\n");
builder.Append("----------------------------\n");
builder.Append($"Version: {Assembly.GetExecutingAssembly().GetName().Version}\n");
builder.Append($"OS: {Environment.OSVersion.ToString()}\n");
builder.Append($"Framework: {AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName}\n");
builder.Append($"Source: {ex.Source}\n");
builder.Append($"---------------------------\n\n");
builder.Append(ex.StackTrace);
while (ex.InnerException != null)
{
ex = ex.InnerException;
builder.Append($"\n\nInnerException::: {ex.GetType().FullName}: {ex.Message}\n");
builder.Append(ex.StackTrace);
}
var time = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
var file = Path.Combine(Native.OS.DataDir, $"crash_{time}.log");
File.WriteAllText(file, builder.ToString());
}
private static void ShowSelfUpdateResult(object data)
{
Dispatcher.UIThread.Post(() =>
{
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: not null } desktop)
{
var dialog = new Views.SelfUpdate()
{
DataContext = new ViewModels.SelfUpdate() { Data = data }
};
dialog.Show(desktop.MainWindow);
}
OpenDialog(new Views.SelfUpdate() { DataContext = new ViewModels.SelfUpdate() { Data = data } });
});
}
@ -549,5 +530,6 @@ namespace SourceGit
private ViewModels.Launcher _launcher = null;
private ResourceDictionary _activeLocale = null;
private ResourceDictionary _themeOverrides = null;
private ResourceDictionary _fontsOverrides = null;
}
}

View file

@ -4,7 +4,7 @@ namespace SourceGit.Commands
{
public class Push : Command
{
public Push(string repo, string local, string remote, string remoteBranch, bool withTags, bool force, bool track, Action<string> onProgress)
public Push(string repo, string local, string remote, string remoteBranch, bool withTags, bool checkSubmodules, bool track, bool force, Action<string> onProgress)
{
_outputHandler = onProgress;
@ -16,6 +16,8 @@ namespace SourceGit.Commands
if (withTags)
Args += "--tags ";
if (checkSubmodules)
Args += "--recurse-submodules=check ";
if (track)
Args += "-u ";
if (force)

View file

@ -28,8 +28,6 @@ namespace SourceGit.Commands
var match = REG_FORMAT().Match(line);
if (!match.Success)
return;
if (line.EndsWith("/", StringComparison.Ordinal))
return; // Ignore changes with git-worktree
var change = new Models.Change() { Path = match.Groups[2].Value };
var status = match.Groups[1].Value;

View file

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
namespace SourceGit.Commands
{
public class QueryRefsContainsCommit : Command
{
public QueryRefsContainsCommit(string repo, string commit)
{
WorkingDirectory = repo;
RaiseError = false;
Args = $"for-each-ref --format=\"%(refname)\" --contains {commit}";
}
public List<Models.Decorator> Result()
{
var rs = new List<Models.Decorator>();
var output = ReadToEnd();
if (!output.IsSuccess)
return rs;
var lines = output.StdOut.Split('\n');
foreach (var line in lines)
{
if (line.StartsWith("refs/heads/", StringComparison.Ordinal))
rs.Add(new() { Name = line.Substring("refs/heads/".Length), Type = Models.DecoratorType.LocalBranchHead });
else if (line.StartsWith("refs/remotes/", StringComparison.Ordinal))
rs.Add(new() { Name = line.Substring("refs/remotes/".Length), Type = Models.DecoratorType.RemoteBranchHead });
else if (line.StartsWith("refs/tags/", StringComparison.Ordinal))
rs.Add(new() { Name = line.Substring("refs/tags/".Length), Type = Models.DecoratorType.Tag });
}
return rs;
}
}
}

View file

@ -1,5 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace SourceGit.Commands
{
@ -19,14 +19,11 @@ namespace SourceGit.Commands
public bool Push(List<Models.Change> changes, string message)
{
var temp = Path.GetTempFileName();
var stream = new FileStream(temp, FileMode.Create);
var writer = new StreamWriter(stream);
var pathsBuilder = new StringBuilder();
var needAdd = new List<Models.Change>();
foreach (var c in changes)
{
writer.WriteLine(c.Path);
pathsBuilder.Append($"\"{c.Path}\" ");
if (c.WorkTree == Models.ChangeState.Added || c.WorkTree == Models.ChangeState.Untracked)
{
@ -44,15 +41,9 @@ namespace SourceGit.Commands
needAdd.Clear();
}
writer.Flush();
stream.Flush();
writer.Close();
stream.Close();
Args = $"stash push -m \"{message}\" --pathspec-from-file=\"{temp}\"";
var succ = Exec();
File.Delete(temp);
return succ;
var paths = pathsBuilder.ToString();
Args = $"stash push -m \"{message}\" -- {paths}";
return Exec();
}
public bool Apply(string name)

View file

@ -97,8 +97,16 @@ namespace SourceGit.Models
public int Color;
}
public enum DotType
{
Default,
Head,
Merge,
}
public class Dot
{
public DotType Type;
public Point Center;
public int Color;
}
@ -128,12 +136,13 @@ namespace SourceGit.Models
_penCount = colors.Count;
}
public static CommitGraph Parse(List<Commit> commits)
public static CommitGraph Parse(List<Commit> commits, bool firstParentOnlyEnabled)
{
double UNIT_WIDTH = 12;
double HALF_WIDTH = 6;
double UNIT_HEIGHT = 28;
double HALF_HEIGHT = 14;
double H_MARGIN = 2;
var temp = new CommitGraph();
var unsolved = new List<PathHelper>();
@ -152,7 +161,7 @@ namespace SourceGit.Models
offsetY += UNIT_HEIGHT;
// Find first curves that links to this commit and marks others that links to this commit ended.
double offsetX = -HALF_WIDTH;
double offsetX = H_MARGIN - HALF_WIDTH;
foreach (var l in unsolved)
{
if (l.Next == commit.SHA)
@ -204,18 +213,26 @@ namespace SourceGit.Models
// Calculate link position of this commit.
Point position = new Point(offsetX, offsetY);
int dotColor = 0;
if (major != null)
{
major.IsMerged = isMerged;
position = new Point(major.LastX, offsetY);
temp.Dots.Add(new Dot() { Center = position, Color = major.Path.Color });
}
else
{
temp.Dots.Add(new Dot() { Center = position, Color = 0 });
dotColor = major.Path.Color;
}
// Deal with parents
Dot anchor = new Dot() { Center = position, Color = dotColor };
if (commit.IsCurrentHead)
anchor.Type = DotType.Head;
else if (commit.Parents.Count > 1)
anchor.Type = DotType.Merge;
else
anchor.Type = DotType.Default;
temp.Dots.Add(anchor);
// Deal with other parents (the first parent has been processed)
if (!firstParentOnlyEnabled)
{
for (int j = 1; j < commit.Parents.Count; j++)
{
var parent = commit.Parents[j];
@ -239,12 +256,13 @@ namespace SourceGit.Models
offsetX += UNIT_WIDTH;
// Create new curve for parent commit that not includes before
var l = new PathHelper(commit.Parents[j], isMerged, colorIdx, position, new Point(offsetX, position.Y + HALF_HEIGHT));
var l = new PathHelper(parent, isMerged, colorIdx, position, new Point(offsetX, position.Y + HALF_HEIGHT));
unsolved.Add(l);
temp.Paths.Add(l.Path);
colorIdx = (colorIdx + 1) % _penCount;
}
}
}
// Remove ended curves from unsolved
foreach (var l in ended)
@ -255,7 +273,7 @@ namespace SourceGit.Models
// Margins & merge state (used by datagrid).
commit.IsMerged = isMerged;
commit.Margin = new Thickness(Math.Max(offsetX + HALF_WIDTH, oldCount * UNIT_WIDTH), 0, 0, 0);
commit.Margin = new Thickness(Math.Max(offsetX + HALF_WIDTH, oldCount * UNIT_WIDTH + H_MARGIN) + H_MARGIN, 0, 0, 0);
// Clean up
ended.Clear();
@ -271,7 +289,7 @@ namespace SourceGit.Models
if (path.Path.Points.Count == 1 && Math.Abs(path.Path.Points[0].Y - endY) < 0.0001)
continue;
path.Add((i + 0.5) * UNIT_WIDTH, endY + HALF_HEIGHT, HALF_HEIGHT, true);
path.Add((i + 0.5) * UNIT_WIDTH + H_MARGIN, endY + HALF_HEIGHT, HALF_HEIGHT, true);
}
unsolved.Clear();

View file

@ -14,5 +14,6 @@
{
public DecoratorType Type { get; set; } = DecoratorType.None;
public string Name { get; set; } = "";
public bool IsTag => Type == DecoratorType.Tag;
}
}

29
src/Models/Hyperlink.cs Normal file
View file

@ -0,0 +1,29 @@
namespace SourceGit.Models
{
public class Hyperlink
{
public int Start { get; set; } = 0;
public int Length { get; set; } = 0;
public string Link { get; set; } = "";
public bool IsCommitSHA { get; set; } = false;
public Hyperlink(int start, int length, string link, bool isCommitSHA = false)
{
Start = start;
Length = length;
Link = link;
IsCommitSHA = isCommitSHA;
}
public bool Intersect(int start, int length)
{
if (start == Start)
return true;
if (start < Start)
return start + length > Start;
return start < Start + Length;
}
}
}

View file

@ -1,29 +1,10 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Avalonia.Controls.Documents;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.Models
{
public class IssueTrackerMatch
{
public int Start { get; set; } = 0;
public int Length { get; set; } = 0;
public string URL { get; set; } = "";
public Run Link { get; set; } = null;
public bool Intersect(int start, int length)
{
if (start == Start)
return true;
if (start < Start)
return start + length > Start;
return start < Start + Length;
}
}
public class IssueTrackerRule : ObservableObject
{
public string Name
@ -65,7 +46,7 @@ namespace SourceGit.Models
set => SetProperty(ref _urlTemplate, value);
}
public void Matches(List<IssueTrackerMatch> outs, string message)
public void Matches(List<Hyperlink> outs, string message)
{
if (_regex == null || string.IsNullOrEmpty(_urlTemplate))
return;
@ -92,17 +73,15 @@ namespace SourceGit.Models
if (intersect)
continue;
var range = new IssueTrackerMatch();
range.Start = start;
range.Length = len;
range.URL = _urlTemplate;
var link = _urlTemplate;
for (var j = 1; j < match.Groups.Count; j++)
{
var group = match.Groups[j];
if (group.Success)
range.URL = range.URL.Replace($"${j}", group.Value);
link = link.Replace($"${j}", group.Value);
}
var range = new Hyperlink(start, len, link);
outs.Add(range);
}
}

View file

@ -10,6 +10,7 @@ namespace SourceGit.Models
public static readonly List<Locale> Supported = new List<Locale>() {
new Locale("English", "en_US"),
new Locale("Deutsch", "de_DE"),
new Locale("Français", "fr_FR"),
new Locale("Português (Brasil)", "pt_BR"),
new Locale("简体中文", "zh_CN"),
new Locale("繁體中文", "zh_TW"),

View file

@ -40,6 +40,12 @@ namespace SourceGit.Models
set;
} = true;
public bool CheckSubmodulesOnPush
{
get;
set;
} = true;
public bool PushAllTags
{
get;

View file

@ -5,7 +5,6 @@ using System.IO;
using System.Runtime.Versioning;
using Avalonia;
using Avalonia.Media;
namespace SourceGit.Native
{
@ -37,11 +36,6 @@ namespace SourceGit.Native
public void SetupApp(AppBuilder builder)
{
builder.With(new FontManagerOptions()
{
DefaultFamilyName = "fonts:SourceGit#JetBrains Mono",
});
builder.With(new X11PlatformOptions()
{
EnableIme = true,

View file

@ -6,20 +6,20 @@ using System.Runtime.Versioning;
using System.Text;
using Avalonia;
using Avalonia.Media;
namespace SourceGit.Native
{
[SupportedOSPlatform("macOS")]
internal class MacOS : OS.IBackend
{
enum TerminalType
{
Default,
iTerm2,
}
public void SetupApp(AppBuilder builder)
{
builder.With(new FontManagerOptions()
{
DefaultFamilyName = "PingFang SC",
});
builder.With(new MacOSPlatformOptions()
{
DisableDefaultApplicationMenuItems = true,
@ -28,7 +28,6 @@ namespace SourceGit.Native
public string FindGitExecutable()
{
// XCode built-in git
return File.Exists("/usr/bin/git") ? "/usr/bin/git" : string.Empty;
}
@ -52,30 +51,42 @@ namespace SourceGit.Native
public void OpenInFileManager(string path, bool select)
{
if (Directory.Exists(path))
{
Process.Start("open", $"\"{path}\"");
}
else if (File.Exists(path))
{
Process.Start("open", $"\"{path}\" -R");
}
}
public void OpenTerminal(string workdir)
{
var dir = string.IsNullOrEmpty(workdir) ? "~" : workdir;
dir = dir.Replace(" ", "\\ ");
var builder = new StringBuilder();
builder.AppendLine("on run argv");
builder.AppendLine(" tell application \"Terminal\"");
builder.AppendLine($" do script \"cd {dir}\"");
builder.AppendLine(" activate");
builder.AppendLine(" end tell");
builder.AppendLine("end run");
var terminal = DetectTerminal();
var cmdBuilder = new StringBuilder();
switch (terminal)
{
case TerminalType.iTerm2:
cmdBuilder.AppendLine("on run argv");
cmdBuilder.AppendLine(" tell application \"iTerm2\"");
cmdBuilder.AppendLine(" create window with default profile");
cmdBuilder.AppendLine(" tell the current session of the current window");
cmdBuilder.AppendLine($" write text \"cd {dir}\"");
cmdBuilder.AppendLine(" end tell");
cmdBuilder.AppendLine(" end tell");
cmdBuilder.AppendLine("end run");
break;
default:
cmdBuilder.AppendLine("on run argv");
cmdBuilder.AppendLine(" tell application \"Terminal\"");
cmdBuilder.AppendLine($" do script \"cd {dir}\"");
cmdBuilder.AppendLine(" activate");
cmdBuilder.AppendLine(" end tell");
cmdBuilder.AppendLine("end run");
break;
}
var tmp = Path.GetTempFileName();
File.WriteAllText(tmp, builder.ToString());
File.WriteAllText(tmp, cmdBuilder.ToString());
var proc = Process.Start("osascript", $"\"{tmp}\"");
if (proc != null)
@ -86,7 +97,15 @@ namespace SourceGit.Native
public void OpenWithDefaultEditor(string file)
{
Process.Start("open", file);
Process.Start("open", $"\"{file}\"");
}
private TerminalType DetectTerminal()
{
if (Directory.Exists("/Applications/iTerm.app"))
return TerminalType.iTerm2;
return TerminalType.Default;
}
}
}

View file

@ -8,7 +8,6 @@ using System.Text;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
namespace SourceGit.Native
{
@ -62,12 +61,6 @@ namespace SourceGit.Native
public void SetupApp(AppBuilder builder)
{
builder.With(new FontManagerOptions()
{
DefaultFamilyName = "Microsoft YaHei UI",
FontFallbacks = [new FontFallback { FontFamily = "Microsoft YaHei" }],
});
// Fix drop shadow issue on Windows 10
RTL_OSVERSIONINFOEX v = new RTL_OSVERSIONINFOEX();
v.dwOSVersionInfoSize = (uint)Marshal.SizeOf<RTL_OSVERSIONINFOEX>();
@ -190,6 +183,7 @@ namespace SourceGit.Native
else
{
fullpath = new DirectoryInfo(path!).FullName;
fullpath += Path.DirectorySeparatorChar;
}
if (select)
@ -209,7 +203,7 @@ namespace SourceGit.Native
public void OpenWithDefaultEditor(string file)
{
var info = new FileInfo(file);
var start = new ProcessStartInfo("cmd", $"/c start {info.FullName}");
var start = new ProcessStartInfo("cmd", $"/c start \"\" \"{info.FullName}\"");
start.CreateNoWindow = true;
Process.Start(start);
}

View file

@ -38,6 +38,7 @@
<StreamGeometry x:Key="Icons.File.Ignore">M416 832H128V128h384v192C512 355 541 384 576 384L768 384v32c0 19 13 32 32 32S832 435 832 416v-64c0-6 0-19-6-25l-256-256c-6-6-19-6-25-6H128A64 64 0 0064 128v704C64 867 93 896 129 896h288c19 0 32-13 32-32S435 832 416 832zM576 172 722 320H576V172zM736 512C614 512 512 614 512 736S614 960 736 960s224-102 224-224S858 512 736 512zM576 736C576 646 646 576 736 576c32 0 58 6 83 26l-218 218c-19-26-26-51-26-83zm160 160c-32 0-64-13-96-32l224-224c19 26 32 58 32 96 0 90-70 160-160 160z</StreamGeometry>
<StreamGeometry x:Key="Icons.File.Remove">M896 320c0-19-6-32-19-45l-192-192c-13-13-26-19-45-19H192c-38 0-64 26-64 64v768c0 38 26 64 64 64h640c38 0 64-26 64-64V320zm-256 384H384c-19 0-32-13-32-32s13-32 32-32h256c19 0 32 13 32 32s-13 32-32 32zm166-384H640V128l192 192h-26z</StreamGeometry>
<StreamGeometry x:Key="Icons.Filter">M599 425 599 657 425 832 425 425 192 192 832 192Z</StreamGeometry>
<StreamGeometry x:Key="Icons.FirstParentFilter">m211 611a142 142 0 00-90-4v-190a142 142 0 0090-4v198zm0 262v150h-90v-146a142 142 0 0090-4zm0-723a142 142 0 00-90-4v-146h90zm-51 246a115 115 0 11115-115 115 115 0 01-115 115zm0 461a115 115 0 11115-115 115 115 0 01-115 115zm256-691h563v90h-563zm0 461h563v90h-563zm0-282h422v90h-422zm0 474h422v90h-422z</StreamGeometry>
<StreamGeometry x:Key="Icons.Folder">M853 267H514c-4 0-6-2-9-4l-38-66c-13-21-38-36-64-36H171c-41 0-75 34-75 75v555c0 41 34 75 75 75h683c41 0 75-34 75-75V341c0-41-34-75-75-75zm-683-43h233c4 0 6 2 9 4l38 66c13 21 38 36 64 36H853c6 0 11 4 11 11v75h-704V235c0-6 4-11 11-11zm683 576H171c-6 0-11-4-11-11V480h704V789c0 6-4 11-11 11z</StreamGeometry>
<StreamGeometry x:Key="Icons.Folder.Add">M1088 227H609L453 78a11 11 0 00-7-3H107a43 43 0 00-43 43v789a43 43 0 0043 43h981a43 43 0 0043-43V270a43 43 0 00-43-43zM757 599c0 5-5 9-10 9h-113v113c0 5-4 9-9 9h-56c-5 0-9-4-9-9V608h-113c-5 0-10-4-10-9V543c0-5 5-9 10-9h113V420c0-5 4-9 9-9h56c5 0 9 4 9 9V533h113c5 0 10 4 10 9v56z</StreamGeometry>
<StreamGeometry x:Key="Icons.Folder.Open">M922 450c-6-9-15-13-26-13h-11V341c0-41-34-75-75-75H514c-4 0-6-2-9-4l-38-66c-13-21-38-36-64-36H171c-41 0-75 34-75 75v597c0 6 2 13 6 19 6 9 15 13 26 13h640c13 0 26-9 30-21l128-363c4-11 2-21-4-30zM171 224h233c4 0 6 2 9 4l38 66c13 21 38 36 64 36H811c6 0 11 4 11 11v96H256c-13 0-26 9-30 21l-66 186V235c0-6 4-11 11-11zm574 576H173l105-299h572l-105 299z</StreamGeometry>
@ -55,7 +56,6 @@
<StreamGeometry x:Key="Icons.Init">M412 66C326 132 271 233 271 347c0 17 1 34 4 50-41-48-98-79-162-83a444 444 0 00-46 196c0 207 142 382 337 439h2c19 0 34 15 34 33 0 11-6 21-14 26l1 14C183 973 0 763 0 511 0 272 166 70 393 7A35 35 0 01414 0c19 0 34 15 34 33a33 33 0 01-36 33zm200 893c86-66 141-168 141-282 0-17-1-34-4-50 41 48 98 79 162 83a444 444 0 0046-196c0-207-142-382-337-439h-2a33 33 0 01-34-33c0-11 6-21 14-26L596 0C841 51 1024 261 1024 513c0 239-166 441-393 504A35 35 0 01610 1024a33 33 0 01-34-33 33 33 0 0136-33zM512 704a192 192 0 110-384 192 192 0 010 384z</StreamGeometry>
<StreamGeometry x:Key="Icons.InteractiveRebase">M512 64A447 447 0 0064 512c0 248 200 448 448 448s448-200 448-448S760 64 512 64zM218 295h31c54 0 105 19 145 55 13 12 13 31 3 43a35 35 0 01-22 10 36 36 0 01-21-7 155 155 0 00-103-39h-31a32 32 0 01-31-31c0-18 13-31 30-31zm31 433h-31a32 32 0 01-31-31c0-16 13-31 31-31h31A154 154 0 00403 512 217 217 0 01620 295h75l-93-67a33 33 0 01-7-43 33 33 0 0143-7l205 148-205 148a29 29 0 01-18 6 32 32 0 01-31-31c0-10 4-19 13-25l93-67H620a154 154 0 00-154 154c0 122-97 220-217 220zm390 118a29 29 0 01-18 6 32 32 0 01-31-31c0-10 4-19 13-25l93-67h-75c-52 0-103-19-143-54-12-12-13-31-1-43a30 30 0 0142-3 151 151 0 00102 39h75L602 599a33 33 0 01-7-43 33 33 0 0143-7l205 148-203 151z</StreamGeometry>
<StreamGeometry x:Key="Icons.Issue">M922 39H102A65 65 0 0039 106v609a65 65 0 0063 68h94v168a34 34 0 0019 31 30 30 0 0012 3 30 30 0 0022-10l182-192H922a65 65 0 0063-68V106A65 65 0 00922 39zM288 378h479a34 34 0 010 68H288a34 34 0 010-68zm0-135h479a34 34 0 010 68H288a34 34 0 010-68zm0 270h310a34 34 0 010 68H288a34 34 0 010-68z</StreamGeometry>
<StreamGeometry x:Key="Icons.Password">M640 96c-158 0-288 130-288 288 0 17 3 31 5 46L105 681 96 691V928h224v-96h96v-96h96v-95c38 18 82 31 128 31 158 0 288-130 288-288s-130-288-288-288zm0 64c123 0 224 101 224 224s-101 224-224 224a235 235 0 01-109-28l-8-4H448v96h-96v96H256v96H160v-146l253-254 12-11-3-17C419 417 416 400 416 384c0-123 101-224 224-224zm64 96a64 64 0 100 128 64 64 0 100-128z</StreamGeometry>
<StreamGeometry x:Key="Icons.LayoutHorizontal">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zM139 832V192c0-6 4-11 11-11h331v661H149c-6 0-11-4-11-11zm747 0c0 6-4 11-11 11H544v-661H875c6 0 11 4 11 11v640z</StreamGeometry>
<StreamGeometry x:Key="Icons.LayoutVertical">M875 117H149C109 117 75 151 75 192v640c0 41 34 75 75 75h725c41 0 75-34 75-75V192c0-41-34-75-75-75zm-725 64h725c6 0 11 4 11 11v288h-747V192c0-6 4-11 11-11zm725 661H149c-6 0-11-4-11-11V544h747V832c0 6-4 11-11 11z</StreamGeometry>
<StreamGeometry x:Key="Icons.LFS">M40 9 15 23 15 31 9 28 9 20 34 5 24 0 0 14 0 34 25 48 25 28 49 14zM26 29 26 48 49 34 49 15z</StreamGeometry>
@ -74,11 +74,13 @@
<StreamGeometry x:Key="Icons.Modified">M896 64H128C96 64 64 96 64 128v768c0 32 32 64 64 64h768c32 0 64-32 64-64V128c0-32-32-64-64-64z m-64 736c0 16-17 32-32 32H224c-18 0-32-12-32-32V224c0-16 16-32 32-32h576c15 0 32 16 32 32v576zM512 384c-71 0-128 57-128 128s57 128 128 128 128-57 128-128-57-128-128-128z</StreamGeometry>
<StreamGeometry x:Key="Icons.Move">M299 811 299 725 384 725 384 811 299 811M469 811 469 725 555 725 555 811 469 811M640 811 640 725 725 725 725 811 640 811M299 640 299 555 384 555 384 640 299 640M469 640 469 555 555 555 555 640 469 640M640 640 640 555 725 555 725 640 640 640M299 469 299 384 384 384 384 469 299 469M469 469 469 384 555 384 555 469 469 469M640 469 640 384 725 384 725 469 640 469M299 299 299 213 384 213 384 299 299 299M469 299 469 213 555 213 555 299 469 299M640 299 640 213 725 213 725 299 640 299Z</StreamGeometry>
<StreamGeometry x:Key="Icons.OpenWith">M683 409v204L1024 308 683 0v191c-413 0-427 526-427 526c117-229 203-307 427-307zm85 492H102V327h153s38-63 114-122H51c-28 0-51 27-51 61v697c0 34 23 61 51 61h768c28 0 51-27 51-61V614l-102 100v187z</StreamGeometry>
<StreamGeometry x:Key="Icons.Password">M640 96c-158 0-288 130-288 288 0 17 3 31 5 46L105 681 96 691V928h224v-96h96v-96h96v-95c38 18 82 31 128 31 158 0 288-130 288-288s-130-288-288-288zm0 64c123 0 224 101 224 224s-101 224-224 224a235 235 0 01-109-28l-8-4H448v96h-96v96H256v96H160v-146l253-254 12-11-3-17C419 417 416 400 416 384c0-123 101-224 224-224zm64 96a64 64 0 100 128 64 64 0 100-128z</StreamGeometry>
<StreamGeometry x:Key="Icons.Paste">M544 85c49 0 90 37 95 85h75a96 96 0 0196 89L811 267a32 32 0 01-28 32L779 299a32 32 0 01-32-28L747 267a32 32 0 00-28-32L715 235h-91a96 96 0 01-80 42H395c-33 0-62-17-80-42L224 235a32 32 0 00-32 28L192 267v576c0 16 12 30 28 32l4 0h128a32 32 0 0132 28l0 4a32 32 0 01-32 32h-128a96 96 0 01-96-89L128 843V267a96 96 0 0189-96L224 171h75a96 96 0 0195-85h150zm256 256a96 96 0 0196 89l0 7v405a96 96 0 01-89 96L800 939h-277a96 96 0 01-96-89L427 843v-405a96 96 0 0189-96L523 341h277zm-256-192H395a32 32 0 000 64h150a32 32 0 100-64z</StreamGeometry>
<StreamGeometry x:Key="Icons.Plus">m186 532 287 0 0 287c0 11 9 20 20 20s20-9 20-20l0-287 287 0c11 0 20-9 20-20s-9-20-20-20l-287 0 0-287c0-11-9-20-20-20s-20 9-20 20l0 287-287 0c-11 0-20 9-20 20s9 20 20 20z</StreamGeometry>
<StreamGeometry x:Key="Icons.Pull">M432 0h160c27 0 48 21 48 48v336h175c36 0 53 43 28 68L539 757c-15 15-40 15-55 0L180 452c-25-25-7-68 28-68H384V48c0-27 21-48 48-48zm592 752v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h293l98 98c40 40 105 40 145 0l98-98H976c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z</StreamGeometry>
<StreamGeometry x:Key="Icons.Push">M592 768h-160c-27 0-48-21-48-48V384h-175c-36 0-53-43-28-68L485 11c15-15 40-15 55 0l304 304c25 25 7 68-28 68H640v336c0 27-21 48-48 48zm432-16v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h272v16c0 62 50 112 112 112h160c62 0 112-50 112-112v-16h272c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z</StreamGeometry>
<StreamGeometry x:Key="Icons.Rebase">M277 85a149 149 0 00-43 292v230a32 32 0 0064 0V555h267A160 160 0 00725 395v-12a149 149 0 10-64-5v17a96 96 0 01-96 96H299V383A149 149 0 00277 85zM228 720a32 32 0 00-37-52 150 150 0 00-53 68 32 32 0 1060 23 85 85 0 0130-39zm136-52a32 32 0 00-37 52 86 86 0 0130 39 32 32 0 1060-23 149 149 0 00-53-68zM204 833a32 32 0 10-55 32 149 149 0 0063 58 32 32 0 0028-57 85 85 0 01-36-33zm202 32a32 32 0 00-55-32 85 85 0 01-36 33 32 32 0 0028 57 149 149 0 0063-58z</StreamGeometry>
<StreamGeometry x:Key="Icons.Relation">M672 336l64-89c-13-19-26-45-26-70 0-64 51-115 109-115s109 51 109 115-51 115-109 115c-19 0-38-6-51-13l-64 89c32 38 51 89 51 147 0 70-32 128-77 172l51 64c13-6 32-13 51-13 57 0 109 51 109 115s-51 109-109 109-109-51-109-115c0-26 13-51 26-70L646 707c-32 19-64 26-102 26-121 0-217-102-217-223v-38l-57-13c-19 32-57 57-96 57C116 515 65 464 65 400s51-115 109-115 109 51 109 115v13l57 19C372 349 448 292 538 292c51 0 102 19 134 45z</StreamGeometry>
<StreamGeometry x:Key="Icons.Remote">M706 302a289 289 0 00-173 44 27 27 0 1029 46 234 234 0 01125-36c23 0 45 3 66 9 93 28 161 114 161 215C914 704 813 805 687 805H337C211 805 110 704 110 580c0-96 61-178 147-210C282 263 379 183 495 183a245 245 0 01210 119z</StreamGeometry>
<StreamGeometry x:Key="Icons.Remote.Add">M364 512h67v108h108v67h-108v108h-67v-108h-108v-67h108v-108zm298-64A107 107 0 01768 555C768 614 720 660 660 660h-108v-54h-108v-108h-94v108h-94c4-21 22-47 44-51l-1-12a75 75 0 0171-75a128 128 0 01239-7a106 106 0 0153-14z</StreamGeometry>
<StreamGeometry x:Key="Icons.RemoveAll">M1024 64v704h-128v128h-128v128h-768v-704h128v-128h128v-128zM64 960h640v-576h-640zM320 128v64h576v512h64v-576zM192 256v64h576v512h64v-576zM432 688L576 832H480L384 736 288 832H192l144-144L192 544h96L384 640l96-96H576z</StreamGeometry>

View file

@ -67,6 +67,8 @@
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Vergleich</x:String>
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
<x:String x:Key="Text.Cancel" xml:space="preserve">ABBRECHEN</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Auf diese Revision zurücksetzen</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Auf Vorgänger-Revision zurücksetzen</x:String>
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">ANZEIGE MODUS ÄNDERN</x:String>
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Zeige als Datei- und Ordnerliste</x:String>
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Zeige als Pfadliste</x:String>
@ -107,7 +109,7 @@
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Commit rückgängig machen</x:String>
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Umformulieren</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Als Patch speichern...</x:String>
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash in den Vorgänger</x:String>
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash Commits</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">ÄNDERUNGEN</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Änderungen durchsuchen...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">DATEIEN</x:String>
@ -117,6 +119,8 @@
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTOR</x:String>
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">GEÄNDERT</x:String>
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Prüfe Refs, die diesen Commit enthalten</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">COMMIT ENTHALTEN IN</x:String>
<x:String x:Key="Text.CommitDetail.Info.GotoChangesPage" xml:space="preserve">Zeigt nur die ersten 100 Änderungen. Alle Änderungen im ÄNDERUNGEN Tab.</x:String>
<x:String x:Key="Text.CommitDetail.Info.Message" xml:space="preserve">COMMIT-NACHRICHT</x:String>
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">VORGÄNGER</x:String>
@ -125,6 +129,9 @@
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Commit-Nachricht</x:String>
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Details</x:String>
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Einstellungen</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">COMMIT TEMPLATE</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Template Name:</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Template Inhalt:</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Adresse</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email Adresse</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
@ -377,14 +384,14 @@
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">Verwende nur die Monospace-Schriftart im Texteditor</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">Design</x:String>
<x:String x:Key="Text.Preference.Appearance.ThemeOverrides" xml:space="preserve">Design-Anpassungen</x:String>
<x:String x:Key="Text.Preference.Appearance.UseFixedTabWidth" xml:space="preserve">Fixe Tab-Breite in Titelleiste</x:String>
<x:String x:Key="Text.Preference.Appearance.UseNativeWindowFrame" xml:space="preserve">Verwende nativen Fensterrahmen</x:String>
<x:String x:Key="Text.Preference.General" xml:space="preserve">ALLGEMEIN</x:String>
<x:String x:Key="Text.Preference.General.Check4UpdatesOnStartup" xml:space="preserve">Beim Starten nach Updates suchen</x:String>
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Sprache</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">Commit-Historie</x:String>
<x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">Zuletzt geöffnete Tabs beim Starten wiederherstellen</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Längenvorgabe für Commit-Nachrichten</x:String>
<x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">Fixe Tab-Breite in Titelleiste</x:String>
<x:String x:Key="Text.Preference.General.VisibleDiffContextLines" xml:space="preserve">Sichtbare Vergleichskontextzeilen</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Remotes automatisch fetchen</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Auto-Fetch Intervall</x:String>
@ -428,6 +435,7 @@
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Rebase anstatt Merge verwenden</x:String>
<x:String x:Key="Text.Push" xml:space="preserve">Push</x:String>
<x:String x:Key="Text.Push.CheckSubmodules" xml:space="preserve">Sicherstellen, dass Submodule gepusht wurden</x:String>
<x:String x:Key="Text.Push.Force" xml:space="preserve">Erzwinge Push</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">Lokaler Branch:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote:</x:String>
@ -475,6 +483,7 @@
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">GEFILTERT:</x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOKALE BRANCHES</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Zum HEAD wechseln</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Aktiviere '--first-parent' Option</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Erstelle Branch</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Öffne in {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Öffne in externen Tools</x:String>
@ -590,11 +599,13 @@
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">Du kannst diese Datei jetzt stagen.</x:String>
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT &amp; PUSH</x:String>
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Template/Historie</x:String>
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">STRG + Enter</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">KONFLIKTE ERKANNT</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">DATEI KONFLIKTE GELÖST</x:String>
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">NICHT-VERFOLGTE DATEIEN INKLUDIEREN</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">KEINE BISHERIGEN COMMIT-NACHRICHTEN</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">KEINE COMMIT TEMPLATES</x:String>
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">GESTAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Staged.Unstage" xml:space="preserve">UNSTAGEN</x:String>
<x:String x:Key="Text.WorkingCopy.Staged.UnstageAll" xml:space="preserve">ALLES UNSTAGEN</x:String>
@ -602,6 +613,7 @@
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGEN</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">ALLES STAGEN</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">ALS UNVERÄNDERT ANGENOMMENE ANZEIGEN</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
<x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Rechtsklick auf selektierte Dateien und wähle die Konfliktlösungen aus.</x:String>
<x:String x:Key="Text.Worktree" xml:space="preserve">WORKTREE</x:String>
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Pfad kopieren</x:String>

View file

@ -107,6 +107,7 @@
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Reword</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Save as Patch...</x:String>
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash Into Parent</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">Squash Child Commits to Here</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CHANGES</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Search Changes...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">FILES</x:String>
@ -116,6 +117,8 @@
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTHOR</x:String>
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">CHANGED</x:String>
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn" xml:space="preserve">Check refs that contains this commit</x:String>
<x:String x:Key="Text.CommitDetail.Info.ContainsIn.Title" xml:space="preserve">COMMIT IS CONTAINED BY</x:String>
<x:String x:Key="Text.CommitDetail.Info.GotoChangesPage" xml:space="preserve">Shows only the first 100 changes. See all changes on the CHANGES tab.</x:String>
<x:String x:Key="Text.CommitDetail.Info.Message" xml:space="preserve">MESSAGE</x:String>
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">PARENTS</x:String>
@ -143,6 +146,7 @@
<x:String x:Key="Text.Configure.User" xml:space="preserve">User Name</x:String>
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">User name for this repository</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Copy</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Copy All Text</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COPY MESSAGE</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Copy Path</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copy File Name</x:String>
@ -241,6 +245,8 @@
<x:String x:Key="Text.FileCM.UseTheirs" xml:space="preserve">Use Theirs (checkout --theirs)</x:String>
<x:String x:Key="Text.FileCM.UseMine" xml:space="preserve">Use Mine (checkout --ours)</x:String>
<x:String x:Key="Text.FileHistory" xml:space="preserve">File History</x:String>
<x:String x:Key="Text.FileHistory.FileContent" xml:space="preserve">CONTENT</x:String>
<x:String x:Key="Text.FileHistory.FileChange" xml:space="preserve">CHANGE</x:String>
<x:String x:Key="Text.Filter" xml:space="preserve">FILTER</x:String>
<x:String x:Key="Text.GitFlow" xml:space="preserve">Git-Flow</x:String>
<x:String x:Key="Text.GitFlow.DevelopBranch" xml:space="preserve">Development Branch:</x:String>
@ -379,14 +385,14 @@
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">Only use monospace font in text editor</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">Theme</x:String>
<x:String x:Key="Text.Preference.Appearance.ThemeOverrides" xml:space="preserve">Theme Overrides</x:String>
<x:String x:Key="Text.Preference.Appearance.UseFixedTabWidth" xml:space="preserve">Use fixed tab width in titlebar</x:String>
<x:String x:Key="Text.Preference.Appearance.UseNativeWindowFrame" xml:space="preserve">Use native window frame</x:String>
<x:String x:Key="Text.Preference.General" xml:space="preserve">GENERAL</x:String>
<x:String x:Key="Text.Preference.General.Check4UpdatesOnStartup" xml:space="preserve">Check for updates on startup</x:String>
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Language</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">History Commits</x:String>
<x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">Restore last opened tab(s) on startup</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Subject Guide Length</x:String>
<x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">Use fixed tab width in titlebar</x:String>
<x:String x:Key="Text.Preference.General.VisibleDiffContextLines" xml:space="preserve">Visible Diff Context Lines</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Fetch remotes automatically</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Auto Fetch Interval</x:String>
@ -430,6 +436,7 @@
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Use rebase instead of merge</x:String>
<x:String x:Key="Text.Push" xml:space="preserve">Push</x:String>
<x:String x:Key="Text.Push.CheckSubmodules" xml:space="preserve">Make sure submodules have been pushed</x:String>
<x:String x:Key="Text.Push.Force" xml:space="preserve">Force push</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">Local Branch:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote:</x:String>
@ -477,6 +484,7 @@
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">FILTERED BY:</x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOCAL BRANCHES</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate To HEAD</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Enable '--first-parent' Option</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Open In {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open In External Tools</x:String>
@ -524,7 +532,8 @@
<x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Skip This Version</x:String>
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Software Update</x:String>
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">There are currently no updates available.</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Squash HEAD Into Parent</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Squash Commits</x:String>
<x:String x:Key="Text.Squash.Into" xml:space="preserve">Into:</x:String>
<x:String x:Key="Text.SSHKey" xml:space="preserve">SSH Private Key:</x:String>
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Private SSH key store path</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">START</x:String>

View file

@ -0,0 +1,626 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="avares://SourceGit/Resources/Locales/en_US.axaml"/>
</ResourceDictionary.MergedDictionaries>
<x:String x:Key="Text.About" xml:space="preserve">A propos</x:String>
<x:String x:Key="Text.About.Menu" xml:space="preserve">A propos de SourceGit</x:String>
<x:String x:Key="Text.About.BuildWith" xml:space="preserve">• Compilé avec </x:String>
<x:String x:Key="Text.About.Copyright" xml:space="preserve">© 2024 sourcegit-scm</x:String>
<x:String x:Key="Text.About.Editor" xml:space="preserve">• TextEditor de </x:String>
<!-- Seemingly not used yet -->
<x:String x:Key="Text.About.Fonts" xml:space="preserve">• La police Monospace vient de </x:String>
<x:String x:Key="Text.About.SourceCode" xml:space="preserve">• Le code source est disponible sur </x:String>
<x:String x:Key="Text.About.SubTitle" xml:space="preserve">Client Git gratuit et open source</x:String>
<x:String x:Key="Text.AddWorktree" xml:space="preserve">Ajouter un Worktree</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout" xml:space="preserve">What to Checkout:</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Branche existante</x:String>
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Créer une nouvelle branche</x:String>
<x:String x:Key="Text.AddWorktree.Location" xml:space="preserve">Location:</x:String>
<x:String x:Key="Text.AddWorktree.Location.Placeholder" xml:space="preserve">Chemin vers ce worktree. Relatif supporté.</x:String>
<x:String x:Key="Text.AddWorktree.Name" xml:space="preserve">Nom de branche:</x:String>
<x:String x:Key="Text.AddWorktree.Name.Placeholder" xml:space="preserve">Optionnel. Par défaut le nom du dossier de destination.</x:String>
<x:String x:Key="Text.AddWorktree.Tracking" xml:space="preserve">Track Branch:</x:String>
<x:String x:Key="Text.AddWorktree.Tracking.Toggle" xml:space="preserve">Tracking remote branch</x:String>
<x:String x:Key="Text.Apply" xml:space="preserve">Patch</x:String>
<x:String x:Key="Text.Apply.Error" xml:space="preserve">Erreur</x:String>
<x:String x:Key="Text.Apply.Error.Desc" xml:space="preserve">Soulever les erreurs et refuser d'appliquer le patch</x:String>
<x:String x:Key="Text.Apply.ErrorAll" xml:space="preserve">Toutes erreurs</x:String>
<x:String x:Key="Text.Apply.ErrorAll.Desc" xml:space="preserve">Similaire à 'error', mais plus détaillé</x:String>
<x:String x:Key="Text.Apply.File" xml:space="preserve">Fichier de patch :</x:String>
<x:String x:Key="Text.Apply.File.Placeholder" xml:space="preserve">Selectionner le fichier .patch à appliquer</x:String>
<x:String x:Key="Text.Apply.IgnoreWS" xml:space="preserve">Ignorer les espaces blancs</x:String>
<x:String x:Key="Text.Apply.NoWarn" xml:space="preserve">Pas d'avertissement</x:String>
<x:String x:Key="Text.Apply.NoWarn.Desc" xml:space="preserve">Désactive l'avertissement des espaces blancs terminaux</x:String>
<x:String x:Key="Text.Apply.Title" xml:space="preserve">Appliquer le patch</x:String>
<x:String x:Key="Text.Apply.Warn" xml:space="preserve">Warn</x:String>
<x:String x:Key="Text.Apply.Warn.Desc" xml:space="preserve">Affiche les avertissements Outputs warnings for a few such errors, mais applique</x:String>
<x:String x:Key="Text.Apply.WS" xml:space="preserve">Espace blanc:</x:String>
<x:String x:Key="Text.Archive" xml:space="preserve">Archive...</x:String>
<x:String x:Key="Text.Archive.File" xml:space="preserve">Sauvegarder l'archive vers :</x:String>
<x:String x:Key="Text.Archive.File.Placeholder" xml:space="preserve">Selectionner le chemin de l'archive</x:String>
<x:String x:Key="Text.Archive.Revision" xml:space="preserve">Révision:</x:String>
<x:String x:Key="Text.Archive.Title" xml:space="preserve">Archive</x:String>
<x:String x:Key="Text.Askpass" xml:space="preserve">SourceGit Askpass</x:String>
<x:String x:Key="Text.AssumeUnchanged" xml:space="preserve">FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">PAS DE FICHIERS PRÉSUMÉS INCHANGÉS</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">REMOVE</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">FICHIER BINAIRE NON SUPPORTÉ !!!</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME SUR CE FICHIER NON SUPPORTÉ !!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Comparer avec la branche</x:String>
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Comparer avec HEAD</x:String>
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Comparer avec le Worktree</x:String>
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copier le nom de la branche</x:String>
<x:String x:Key="Text.BranchCM.Delete" xml:space="preserve">Supprimer ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.DeleteMultiBranches" xml:space="preserve">Supprimer {0} branches sélectionnées</x:String>
<x:String x:Key="Text.BranchCM.DiscardAll" xml:space="preserve">Rejeter tous les changements</x:String>
<x:String x:Key="Text.BranchCM.FastForward" xml:space="preserve">Fast-Forward to ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Finish" xml:space="preserve">Git Flow - Finir ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Merge" xml:space="preserve">Merger ${0}$ dans ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Pull" xml:space="preserve">Pull ${0}$</x:String>
<x:String x:Key="Text.BranchCM.PullInto" xml:space="preserve">Pull ${0}$ dans ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Push" xml:space="preserve">Push ${0}$</x:String>
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ sur ${1}$...</x:String>
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Renommer ${0}$...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Définir la branche de suivi</x:String>
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">Unset Upstream</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Comparer les branches</x:String>
<x:String x:Key="Text.Bytes" xml:space="preserve">Octets</x:String>
<x:String x:Key="Text.Cancel" xml:space="preserve">ANNULER</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutThisRevision" xml:space="preserve">Reset vers cette révision</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Reset vers la révision parente</x:String>
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">CHANGER LE MODE D'AFFICHAGE</x:String>
<x:String x:Key="Text.ChangeDisplayMode.Grid" xml:space="preserve">Afficher comme liste de dossiers/fichiers</x:String>
<x:String x:Key="Text.ChangeDisplayMode.List" xml:space="preserve">Afficher comme liste de chemins</x:String>
<x:String x:Key="Text.ChangeDisplayMode.Tree" xml:space="preserve">Afficher comme arborescence</x:String>
<x:String x:Key="Text.Checkout" xml:space="preserve">Checkout Branch</x:String>
<x:String x:Key="Text.Checkout.Commit" xml:space="preserve">Checkout Commit</x:String>
<x:String x:Key="Text.Checkout.Commit.Warning" xml:space="preserve">Avertissement: un checkout vers un commit aboutiera vers un HEAD détaché</x:String>
<x:String x:Key="Text.Checkout.Commit.Target" xml:space="preserve">Commit :</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branche :</x:String>
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Changement locaux:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Rejeter</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.DoNothing" xml:space="preserve">Ne rien faire</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash et Réappliquer</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry-Pick ce commit</x:String>
<x:String x:Key="Text.CherryPick.Commit" xml:space="preserve">Commit :</x:String>
<x:String x:Key="Text.CherryPick.CommitChanges" xml:space="preserve">Commit tous les changements</x:String>
<x:String x:Key="Text.CherryPick.Title" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.ClearStashes" xml:space="preserve">Vider les Stashes</x:String>
<x:String x:Key="Text.ClearStashes.Message" xml:space="preserve">Voulez-vous vider tous les stashes. Êtes-vous sûr de vouloir continuer ?</x:String>
<x:String x:Key="Text.Clone" xml:space="preserve">Cloner le dépôt distant</x:String>
<x:String x:Key="Text.Clone.AdditionalParam" xml:space="preserve">Paramètres supplémentaires :</x:String>
<x:String x:Key="Text.Clone.AdditionalParam.Placeholder" xml:space="preserve">Arguments additionnels au clônage. Optionnel.</x:String>
<x:String x:Key="Text.Clone.LocalName" xml:space="preserve">Nom local :</x:String>
<x:String x:Key="Text.Clone.LocalName.Placeholder" xml:space="preserve">Nom de dépôt. Optionnel.</x:String>
<x:String x:Key="Text.Clone.ParentFolder" xml:space="preserve">Dossier parent :</x:String>
<x:String x:Key="Text.Clone.RemoteURL" xml:space="preserve">URL du dépôt :</x:String>
<x:String x:Key="Text.Close" xml:space="preserve">FERMER</x:String>
<x:String x:Key="Text.CodeEditor" xml:space="preserve">Editeur</x:String>
<x:String x:Key="Text.CommitCM.CherryPick" xml:space="preserve">Cherry-Pick ce commit</x:String>
<x:String x:Key="Text.CommitCM.Checkout" xml:space="preserve">Checkout ce commit</x:String>
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Comparer avec HEAD</x:String>
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Comparer avec le Worktree</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copier les infos</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copier le SHA</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Rebase interactif de ${0}$ ici</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ ici</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ ici</x:String>
<x:String x:Key="Text.CommitCM.Revert" xml:space="preserve">Annuler le commit</x:String>
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">Reformuler</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">Sauver en tant que patch...</x:String>
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">Squash dans le parent</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">CHANGEMENTS</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">Chercher des changements...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">FICHIERS</x:String>
<x:String x:Key="Text.CommitDetail.Files.LFS" xml:space="preserve">Fichiers LFS</x:String>
<x:String x:Key="Text.CommitDetail.Files.Submodule" xml:space="preserve">Sous-module</x:String>
<x:String x:Key="Text.CommitDetail.Info" xml:space="preserve">INFORMATION</x:String>
<x:String x:Key="Text.CommitDetail.Info.Author" xml:space="preserve">AUTEUR</x:String>
<x:String x:Key="Text.CommitDetail.Info.Changed" xml:space="preserve">CHANGÉ</x:String>
<x:String x:Key="Text.CommitDetail.Info.Committer" xml:space="preserve">COMMITTER</x:String>
<x:String x:Key="Text.CommitDetail.Info.GotoChangesPage" xml:space="preserve">Afficher seulement les 100 premiers changements. Voir tous les changements dans l'onglet CHANGEMENTS.</x:String>
<x:String x:Key="Text.CommitDetail.Info.Message" xml:space="preserve">MESSAGE</x:String>
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">PARENTS</x:String>
<x:String x:Key="Text.CommitDetail.Info.Refs" xml:space="preserve">REFS</x:String>
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Enter le sujet du commit</x:String>
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Description</x:String>
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Configurer</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">MODÈLE DE COMMIT</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">Nom de modèle:</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">Contenu de modèle:</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Addresse e-mail</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Addresse e-mail</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">ISSUE TRACKER</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Add Sample Github Rule</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleJira" xml:space="preserve">Add Sample Jira Rule</x:String>
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">Nouvelle règle</x:String>
<x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">Issue Regex Expression:</x:String>
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">nom de règle :</x:String>
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">URL résultant:</x:String>
<!-- A vérifier -->
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Please use $1, $2 to access regex groups values.</x:String>
<x:String x:Key="Text.Configure.Proxy" xml:space="preserve">HTTP Proxy</x:String>
<x:String x:Key="Text.Configure.Proxy.Placeholder" xml:space="preserve">HTTP proxy used by this repository</x:String>
<x:String x:Key="Text.Configure.User" xml:space="preserve">Nom d'utilisateur</x:String>
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">Nom d'utilisateur pour ce dépôt</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Copier</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COPIER LE MESSAGE</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Copier le chemin</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">Copier le nom de fichier</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Créer une branche...</x:String>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Basé sur :</x:String>
<!-- A vérifier si féminin-->
<x:String x:Key="Text.CreateBranch.Checkout" xml:space="preserve">Check out the created branch</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges" xml:space="preserve">Changements locaux :</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.Discard" xml:space="preserve">Rejeter</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.DoNothing" xml:space="preserve">Ne rien faire</x:String>
<x:String x:Key="Text.CreateBranch.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Réappliquer</x:String>
<x:String x:Key="Text.CreateBranch.Name" xml:space="preserve">Nouveau nom de branche:</x:String>
<x:String x:Key="Text.CreateBranch.Name.Placeholder" xml:space="preserve">Enter le nom de branche.</x:String>
<x:String x:Key="Text.CreateBranch.Title" xml:space="preserve">Créer une branche locale</x:String>
<x:String x:Key="Text.CreateTag" xml:space="preserve">Créer un tag...</x:String>
<x:String x:Key="Text.CreateTag.BasedOn" xml:space="preserve">Nouveau tag à :</x:String>
<x:String x:Key="Text.CreateTag.GPGSign" xml:space="preserve">Signature GPG</x:String>
<x:String x:Key="Text.CreateTag.Message" xml:space="preserve">Message de tag :</x:String>
<x:String x:Key="Text.CreateTag.Message.Placeholder" xml:space="preserve">Optionnel.</x:String>
<x:String x:Key="Text.CreateTag.Name" xml:space="preserve">Nom de tag :</x:String>
<x:String x:Key="Text.CreateTag.Name.Placeholder" xml:space="preserve">Format Recommendé : v1.0.0-alpha</x:String>
<x:String x:Key="Text.CreateTag.PushToAllRemotes" xml:space="preserve">Push vers tous les arpès création</x:String>
<x:String x:Key="Text.CreateTag.Title" xml:space="preserve">Créer un nouveau tag</x:String>
<x:String x:Key="Text.CreateTag.Type" xml:space="preserve">Kind:</x:String>
<x:String x:Key="Text.CreateTag.Type.Annotated" xml:space="preserve">annoté</x:String>
<!-- A vérifier si féminin-->
<x:String x:Key="Text.CreateTag.Type.Lightweight" xml:space="preserve">lightweight</x:String>
<x:String x:Key="Text.CtrlClickTip" xml:space="preserve">Maintenir Ctrl pour commencer directement</x:String>
<x:String x:Key="Text.Cut" xml:space="preserve">Couper</x:String>
<x:String x:Key="Text.DeleteBranch" xml:space="preserve">Supprimer la branche</x:String>
<x:String x:Key="Text.DeleteBranch.Branch" xml:space="preserve">Branche :</x:String>
<x:String x:Key="Text.DeleteBranch.IsRemoteTip" xml:space="preserve">Vous êtes sur le point de supprimer une branche distante !!!</x:String>
<x:String x:Key="Text.DeleteBranch.WithTrackingRemote" xml:space="preserve">Supprimer également la branche distante ${0}$</x:String>
<x:String x:Key="Text.DeleteMultiBranch" xml:space="preserve">Supprimer plusieurs branches</x:String>
<x:String x:Key="Text.DeleteMultiBranch.Tip" xml:space="preserve">Vous essayez de supprimer plusieurs branche à la fois. Assurez-vous de revérifier avant de procéder !</x:String>
<x:String x:Key="Text.DeleteRemote" xml:space="preserve">Supprimer Remote</x:String>
<x:String x:Key="Text.DeleteRemote.Remote" xml:space="preserve">Remote :</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.Target" xml:space="preserve">Cible :</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.TitleForGroup" xml:space="preserve">Confirmer la suppression du groupe</x:String>
<x:String x:Key="Text.DeleteRepositoryNode.TitleForRepository" xml:space="preserve">Confirmer la suppression du dépôt</x:String>
<x:String x:Key="Text.DeleteSubmodule" xml:space="preserve">Supprimer le Sous-module</x:String>
<x:String x:Key="Text.DeleteSubmodule.Path" xml:space="preserve">Chemin du sous-module :</x:String>
<x:String x:Key="Text.DeleteTag" xml:space="preserve">Supprimer le tag</x:String>
<x:String x:Key="Text.DeleteTag.Tag" xml:space="preserve">Tag:</x:String>
<x:String x:Key="Text.DeleteTag.WithRemote" xml:space="preserve">Delete from remote repositories</x:String>
<x:String x:Key="Text.Diff.Binary" xml:space="preserve">DIFF BINAIRE</x:String>
<x:String x:Key="Text.Diff.Binary.New" xml:space="preserve">NOUVEAU</x:String>
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">ANCIEN</x:String>
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">Copier</x:String>
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">Mode de fichier changé</x:String>
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS OBJECT CHANGE</x:String>
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Différence suivante</x:String>
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">PAS DE CHANGEMENT OU SEULEMENT EN FIN DE LIGNE</x:String>
<x:String x:Key="Text.Diff.Prev" xml:space="preserve">Différence précédente</x:String>
<x:String x:Key="Text.Diff.SideBySide" xml:space="preserve">Diff côte-à-côte</x:String>
<x:String x:Key="Text.Diff.Submodule" xml:space="preserve">SOUS-MODULE</x:String>
<x:String x:Key="Text.Diff.Submodule.New" xml:space="preserve">NOUVEAU</x:String>
<x:String x:Key="Text.Diff.SyntaxHighlight" xml:space="preserve">Syntax Highlighting</x:String>
<x:String x:Key="Text.Diff.ToggleWordWrap" xml:space="preserve">Retour à la ligne</x:String>
<x:String x:Key="Text.Diff.UseMerger" xml:space="preserve">Ouvrir dans l'outil de merge</x:String>
<x:String x:Key="Text.Diff.VisualLines.Decr" xml:space="preserve">Réduit le nombre de ligne visibles</x:String>
<x:String x:Key="Text.Diff.VisualLines.Incr" xml:space="preserve">Augmente le nombre de ligne visibles</x:String>
<x:String x:Key="Text.Diff.Welcome" xml:space="preserve">SELECTIONNER UN FICHIER POUR VOIR LES CHANGEMENTS</x:String>
<x:String x:Key="Text.Diff.ShowHiddenSymbols" xml:space="preserve">Afficher les caractères invisibles</x:String>
<x:String x:Key="Text.Diff.SwapCommits" xml:space="preserve">Permuter</x:String>
<x:String x:Key="Text.DiffWithMerger" xml:space="preserve">Ouvrir dans l'outil de merge</x:String>
<x:String x:Key="Text.Discard" xml:space="preserve">Rejeter les changements</x:String>
<x:String x:Key="Text.Discard.All" xml:space="preserve">Tous les changements dans la copie de travail.</x:String>
<x:String x:Key="Text.Discard.Changes" xml:space="preserve">Changements :</x:String>
<x:String x:Key="Text.Discard.Total" xml:space="preserve">{0} changements seront rejetés</x:String>
<x:String x:Key="Text.Discard.Warning" xml:space="preserve">Vous ne pouvez pas annuler cette action !!!</x:String>
<x:String x:Key="Text.EditRepositoryNode.Bookmark" xml:space="preserve">Bookmark:</x:String>
<x:String x:Key="Text.EditRepositoryNode.Name" xml:space="preserve">Nouveau nom:</x:String>
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Cible :</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Éditer le groupe sélectionné</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Éditer le dépôt sélectionné</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (sans checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch toutes les branches distantes</x:String>
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">Fetch sans les tags</x:String>
<x:String x:Key="Text.Fetch.Prune" xml:space="preserve">Purger les branches distantes mortes</x:String>
<x:String x:Key="Text.Fetch.Remote" xml:space="preserve">Remote :</x:String>
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">Fetch des changements distants</x:String>
<x:String x:Key="Text.FileCM.AssumeUnchanged" xml:space="preserve">Présumer inchangé</x:String>
<x:String x:Key="Text.FileCM.Discard" xml:space="preserve">Rejeter...</x:String>
<x:String x:Key="Text.FileCM.DiscardMulti" xml:space="preserve">Rejeter {0} fichiers...</x:String>
<x:String x:Key="Text.FileCM.DiscardSelectedLines" xml:space="preserve">Rejeter les changements dans les lignes sélectionnées</x:String>
<x:String x:Key="Text.FileCM.OpenWithExternalMerger" xml:space="preserve">Ouvrir l'outil de merge externe</x:String>
<x:String x:Key="Text.FileCM.SaveAsPatch" xml:space="preserve">Savegarder le patch sous...</x:String>
<x:String x:Key="Text.FileCM.Stage" xml:space="preserve">Stage</x:String>
<!-- Est-ce un verbe ou un nom ? -->
<x:String x:Key="Text.FileCM.StageMulti" xml:space="preserve">Stage {0} files</x:String>
<x:String x:Key="Text.FileCM.StageSelectedLines" xml:space="preserve">Stage Changes in Selected Line(s)</x:String>
<x:String x:Key="Text.FileCM.Stash" xml:space="preserve">Stash...</x:String>
<x:String x:Key="Text.FileCM.StashMulti" xml:space="preserve">Stash {0} fichiers...</x:String>
<x:String x:Key="Text.FileCM.Unstage" xml:space="preserve">Unstage</x:String>
<x:String x:Key="Text.FileCM.UnstageMulti" xml:space="preserve">Unstage {0} files</x:String>
<x:String x:Key="Text.FileCM.UnstageSelectedLines" xml:space="preserve">Unstage Changes in Selected Line(s)</x:String>
<x:String x:Key="Text.FileCM.UseTheirs" xml:space="preserve">Use Theirs (checkout --theirs)</x:String>
<x:String x:Key="Text.FileCM.UseMine" xml:space="preserve">Use Mine (checkout --ours)</x:String>
<x:String x:Key="Text.FileHistory" xml:space="preserve">File History</x:String>
<x:String x:Key="Text.Filter" xml:space="preserve">FILTER</x:String>
<x:String x:Key="Text.GitFlow" xml:space="preserve">Git-Flow</x:String>
<x:String x:Key="Text.GitFlow.DevelopBranch" xml:space="preserve">Development Branch:</x:String>
<x:String x:Key="Text.GitFlow.Feature" xml:space="preserve">Feature:</x:String>
<x:String x:Key="Text.GitFlow.FeaturePrefix" xml:space="preserve">Feature Prefix:</x:String>
<x:String x:Key="Text.GitFlow.FinishFeature" xml:space="preserve">FLOW - Finish Feature</x:String>
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finish Hotfix</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finish Release</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Hotfix Prefix:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Initialize Git-Flow</x:String>
<x:String x:Key="Text.GitFlow.KeepBranchAfterFinish" xml:space="preserve">Keep branch</x:String>
<x:String x:Key="Text.GitFlow.ProductionBranch" xml:space="preserve">Production Branch:</x:String>
<x:String x:Key="Text.GitFlow.Release" xml:space="preserve">Release:</x:String>
<x:String x:Key="Text.GitFlow.ReleasePrefix" xml:space="preserve">Release Prefix:</x:String>
<x:String x:Key="Text.GitFlow.StartFeature" xml:space="preserve">Start Feature...</x:String>
<x:String x:Key="Text.GitFlow.StartFeatureTitle" xml:space="preserve">FLOW - Start Feature</x:String>
<x:String x:Key="Text.GitFlow.StartHotfix" xml:space="preserve">Start Hotfix...</x:String>
<x:String x:Key="Text.GitFlow.StartHotfixTitle" xml:space="preserve">FLOW - Start Hotfix</x:String>
<x:String x:Key="Text.GitFlow.StartPlaceholder" xml:space="preserve">Enter name</x:String>
<x:String x:Key="Text.GitFlow.StartRelease" xml:space="preserve">Start Release...</x:String>
<x:String x:Key="Text.GitFlow.StartReleaseTitle" xml:space="preserve">FLOW - Start Release</x:String>
<x:String x:Key="Text.GitFlow.TagPrefix" xml:space="preserve">Version Tag Prefix:</x:String>
<x:String x:Key="Text.GitLFS" xml:space="preserve">Git LFS</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern" xml:space="preserve">Add Track Pattern...</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.IsFilename" xml:space="preserve">Pattern is file name</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Pattern" xml:space="preserve">Custom Pattern:</x:String>
<x:String x:Key="Text.GitLFS.AddTrackPattern.Title" xml:space="preserve">Add Track Pattern to Git LFS</x:String>
<x:String x:Key="Text.GitLFS.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Title" xml:space="preserve">Fetch LFS Objects</x:String>
<x:String x:Key="Text.GitLFS.Fetch.Tips" xml:space="preserve">Run `git lfs fetch` to download Git LFS objects. This does not update the working copy.</x:String>
<x:String x:Key="Text.GitLFS.Install" xml:space="preserve">Install Git LFS hooks</x:String>
<x:String x:Key="Text.GitLFS.Locks" xml:space="preserve">Show Locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">No Locked Files</x:String>
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">Lock</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS Locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Unlock</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Force Unlock</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">Prune</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">Run `git lfs prune` to delete old LFS files from local storage</x:String>
<x:String x:Key="Text.GitLFS.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.GitLFS.Pull.Title" xml:space="preserve">Pull LFS Objects</x:String>
<x:String x:Key="Text.GitLFS.Pull.Tips" xml:space="preserve">Run `git lfs pull` to download all Git LFS files for current ref &amp; checkout</x:String>
<x:String x:Key="Text.GitLFS.Push" xml:space="preserve">Push</x:String>
<x:String x:Key="Text.GitLFS.Push.Title" xml:space="preserve">Push LFS Objects</x:String>
<x:String x:Key="Text.GitLFS.Push.Tips" xml:space="preserve">Push queued large files to the Git LFS endpoint</x:String>
<x:String x:Key="Text.GitLFS.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.GitLFS.Track" xml:space="preserve">Track files named '{0}'</x:String>
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">Track all *{0} files</x:String>
<x:String x:Key="Text.Histories" xml:space="preserve">Histories</x:String>
<x:String x:Key="Text.Histories.DisplayMode" xml:space="preserve">Switch Horizontal/Vertical Layout</x:String>
<x:String x:Key="Text.Histories.GraphMode" xml:space="preserve">Switch Curve/Polyline Graph Mode</x:String>
<x:String x:Key="Text.Histories.Header.Author" xml:space="preserve">AUTHOR</x:String>
<x:String x:Key="Text.Histories.Header.GraphAndSubject" xml:space="preserve">GRAPH &amp; SUBJECT</x:String>
<x:String x:Key="Text.Histories.Header.SHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.Histories.Header.Time" xml:space="preserve">COMMIT TIME</x:String>
<x:String x:Key="Text.Histories.Search" xml:space="preserve">SEARCH SHA/SUBJECT/AUTHOR. PRESS ENTER TO SEARCH, ESC TO QUIT</x:String>
<x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">CLEAR</x:String>
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">SELECTED {0} COMMITS</x:String>
<x:String x:Key="Text.Hotkeys" xml:space="preserve">Référence des raccourcis clavier</x:String>
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">GLOBAL</x:String>
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">Annuler le popup en cours</x:String>
<x:String x:Key="Text.Hotkeys.Global.CloseTab" xml:space="preserve">Fermer la page en cours</x:String>
<x:String x:Key="Text.Hotkeys.Global.GotoPrevTab" xml:space="preserve">Aller à la page précédente</x:String>
<x:String x:Key="Text.Hotkeys.Global.GotoNextTab" xml:space="preserve">Aller à la page suivante</x:String>
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Créer une nouvelle page</x:String>
<x:String x:Key="Text.Hotkeys.Global.OpenPreference" xml:space="preserve">Ouvrir le dialogue des préférences</x:String>
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">DÉPÔT</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Commit les changements de l'index</x:String>
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Commit et pousser les changements de l'index</x:String>
<x:String x:Key="Text.Hotkeys.Repo.GoHome" xml:space="preserve">Mode tableau de bord (Défaut)</x:String>
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">Forcer le rechargement du dépôt</x:String>
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">Ajouter/Retirer les changements sélectionnés de l'index</x:String>
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">Recherche de commit</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewChanges" xml:space="preserve">Basculer vers 'Changements'</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewHistories" xml:space="preserve">Basculer vers 'Historique'</x:String>
<x:String x:Key="Text.Hotkeys.Repo.ViewStashes" xml:space="preserve">Basculer vers 'Stashes'</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor" xml:space="preserve">ÉDITEUR DE TEXTE</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.CloseSearch" xml:space="preserve">Fermer le panneau de recherche</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.GotoNextMatch" xml:space="preserve">Trouver la prochaine correspondance</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.GotoPrevMatch" xml:space="preserve">Trouver la correspondance précédente</x:String>
<x:String x:Key="Text.Hotkeys.TextEditor.Search" xml:space="preserve">Ouvrir le panneau de recherche</x:String>
<x:String x:Key="Text.Hunk.Stage" xml:space="preserve">Stage</x:String>
<x:String x:Key="Text.Hunk.Unstage" xml:space="preserve">Retirer de l'index</x:String>
<x:String x:Key="Text.Hunk.Discard" xml:space="preserve">Rejeter</x:String>
<x:String x:Key="Text.Init" xml:space="preserve">Initialize Repository</x:String>
<x:String x:Key="Text.Init.Path" xml:space="preserve">Path:</x:String>
<x:String x:Key="Text.Init.Tip" xml:space="preserve">Invalid repository detected. Run `git init` under this path?</x:String>
<x:String x:Key="Text.InProgress.CherryPick" xml:space="preserve">Cherry-Pick in progress. Press 'Abort' to restore original HEAD.</x:String>
<x:String x:Key="Text.InProgress.Merge" xml:space="preserve">Merge request in progress. Press 'Abort' to restore original HEAD.</x:String>
<x:String x:Key="Text.InProgress.Rebase" xml:space="preserve">Rebase in progress. Press 'Abort' to restore original HEAD.</x:String>
<x:String x:Key="Text.InProgress.Revert" xml:space="preserve">Revert in progress. Press 'Abort' to restore original HEAD.</x:String>
<x:String x:Key="Text.InteractiveRebase" xml:space="preserve">Interactive Rebase</x:String>
<x:String x:Key="Text.InteractiveRebase.Target" xml:space="preserve">Target Branch:</x:String>
<x:String x:Key="Text.InteractiveRebase.On" xml:space="preserve">On:</x:String>
<x:String x:Key="Text.InteractiveRebase.MoveUp" xml:space="preserve">Move Up</x:String>
<x:String x:Key="Text.InteractiveRebase.MoveDown" xml:space="preserve">Move Down</x:String>
<x:String x:Key="Text.Launcher" xml:space="preserve">Source Git</x:String>
<x:String x:Key="Text.Launcher.Error" xml:space="preserve">ERROR</x:String>
<x:String x:Key="Text.Launcher.Info" xml:space="preserve">NOTICE</x:String>
<x:String x:Key="Text.Launcher.Menu" xml:space="preserve">Open Main Menu</x:String>
<x:String x:Key="Text.Merge" xml:space="preserve">Merge Branch</x:String>
<x:String x:Key="Text.Merge.Into" xml:space="preserve">Into:</x:String>
<x:String x:Key="Text.Merge.Mode" xml:space="preserve">Merge Option:</x:String>
<x:String x:Key="Text.Merge.Source" xml:space="preserve">Source Branch:</x:String>
<x:String x:Key="Text.Name" xml:space="preserve">Nom :</x:String>
<x:String x:Key="Text.NotConfigured" xml:space="preserve">Git n'a PAS été configuré. Veuillez d'abord le faire dans le menu Préférence.</x:String>
<x:String x:Key="Text.Notice" xml:space="preserve">NOTICE</x:String>
<x:String x:Key="Text.OpenAppDataDir" xml:space="preserve">Ouvrir le dossier AppData</x:String>
<x:String x:Key="Text.OpenFolder" xml:space="preserve">SELECT FOLDER</x:String>
<x:String x:Key="Text.OpenWith" xml:space="preserve">Open With...</x:String>
<x:String x:Key="Text.Optional" xml:space="preserve">Optional.</x:String>
<x:String x:Key="Text.PageTabBar.New" xml:space="preserve">Créer un nouvel onglet</x:String>
<x:String x:Key="Text.PageTabBar.Tab.Bookmark" xml:space="preserve">Bookmark</x:String>
<x:String x:Key="Text.PageTabBar.Tab.Close" xml:space="preserve">Fermer l'onglet</x:String>
<x:String x:Key="Text.PageTabBar.Tab.CloseOther" xml:space="preserve">Fermer les autres onglets</x:String>
<x:String x:Key="Text.PageTabBar.Tab.CloseRight" xml:space="preserve">Fermer les onglets à droite</x:String>
<x:String x:Key="Text.PageTabBar.Tab.CopyPath" xml:space="preserve">Copy Repository Path</x:String>
<x:String x:Key="Text.PageTabBar.Welcome.Title" xml:space="preserve">Dépôts</x:String>
<x:String x:Key="Text.Paste" xml:space="preserve">Paste</x:String>
<x:String x:Key="Text.Period.JustNow" xml:space="preserve">A l'instant</x:String>
<x:String x:Key="Text.Period.MinutesAgo" xml:space="preserve">il y a {0} minutes</x:String>
<x:String x:Key="Text.Period.HoursAgo" xml:space="preserve">il y a {0} heures</x:String>
<x:String x:Key="Text.Period.Yesterday" xml:space="preserve">Hier</x:String>
<x:String x:Key="Text.Period.DaysAgo" xml:space="preserve">il y a {0} jours</x:String>
<x:String x:Key="Text.Period.LastMonth" xml:space="preserve">Le mois dernier</x:String>
<x:String x:Key="Text.Period.MonthsAgo" xml:space="preserve">il y a {0} mois</x:String>
<x:String x:Key="Text.Period.LastYear" xml:space="preserve">L'an dernier</x:String>
<x:String x:Key="Text.Period.YearsAgo" xml:space="preserve">il y a {0} ans</x:String>
<x:String x:Key="Text.Preference" xml:space="preserve">Préférences</x:String>
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">APPARENCE</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">Police par défaut</x:String>
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">Taille de police par défaut</x:String>
<x:String x:Key="Text.Preference.Appearance.MonospaceFont" xml:space="preserve">Police monospace</x:String>
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">N'utiliser que des polices monospace pour l'éditeur de texte</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">Thème</x:String>
<x:String x:Key="Text.Preference.Appearance.ThemeOverrides" xml:space="preserve">Dérogations de thème</x:String>
<x:String x:Key="Text.Preference.Appearance.UseFixedTabWidth" xml:space="preserve">Utiliser des onglets de taille fixe dans la barre de titre</x:String>
<x:String x:Key="Text.Preference.Appearance.UseNativeWindowFrame" xml:space="preserve">Utiliser un cadre de fenêtre natif</x:String>
<x:String x:Key="Text.Preference.General" xml:space="preserve">GÉNÉRAL</x:String>
<x:String x:Key="Text.Preference.General.Check4UpdatesOnStartup" xml:space="preserve">Vérifier les mises à jour au démarrage</x:String>
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Language</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">Historique de commits</x:String>
<x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">Restaurer les onglets au démarrage</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Guide de longueur du sujet</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Fetch les dépôts distants automatiquement</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Intervalle de fetch auto</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetchIntervalSuffix" xml:space="preserve">minute(s)</x:String>
<x:String x:Key="Text.Preference.Git.CRLF" xml:space="preserve">Activer auto CRLF</x:String>
<x:String x:Key="Text.Preference.Git.DefaultCloneDir" xml:space="preserve">Répertoire de clônage par défaut</x:String>
<x:String x:Key="Text.Preference.Git.Email" xml:space="preserve">E-mail utilsateur</x:String>
<x:String x:Key="Text.Preference.Git.Email.Placeholder" xml:space="preserve">E-mail utilsateur global</x:String>
<x:String x:Key="Text.Preference.Git.Path" xml:space="preserve">Chemin d'installation</x:String>
<x:String x:Key="Text.Preference.Git.Shell" xml:space="preserve">Shell</x:String>
<x:String x:Key="Text.Preference.Git.User" xml:space="preserve">Nom d'utilisateur</x:String>
<x:String x:Key="Text.Preference.Git.User.Placeholder" xml:space="preserve">Nom d'utilisateur global</x:String>
<x:String x:Key="Text.Preference.Git.Version" xml:space="preserve">Version de Git</x:String>
<x:String x:Key="Text.Preference.Git.Invalid" xml:space="preserve">Cette application requière Git (>= 2.23.0)</x:String>
<x:String x:Key="Text.Preference.GPG" xml:space="preserve">SIGNATURE GPG</x:String>
<x:String x:Key="Text.Preference.GPG.CommitEnabled" xml:space="preserve">Signature GPG de commit</x:String>
<x:String x:Key="Text.Preference.GPG.TagEnabled" xml:space="preserve">Signature GPG de tag</x:String>
<x:String x:Key="Text.Preference.GPG.Format" xml:space="preserve">Format GPG</x:String>
<x:String x:Key="Text.Preference.GPG.Path" xml:space="preserve">Chemin d'installation du programme</x:String>
<x:String x:Key="Text.Preference.GPG.Path.Placeholder" xml:space="preserve">Saisir le chemin d'installation vers le programme GPG</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey" xml:space="preserve">Clé de signature de l'utilisateur</x:String>
<x:String x:Key="Text.Preference.GPG.UserKey.Placeholder" xml:space="preserve">Clé de signature GPG de l'utilisateur</x:String>
<x:String x:Key="Text.Preference.DiffMerge" xml:space="preserve">OUTIL DIFF/MERGE</x:String>
<x:String x:Key="Text.Preference.DiffMerge.Path" xml:space="preserve">Chemin d'installation</x:String>
<x:String x:Key="Text.Preference.DiffMerge.Path.Placeholder" xml:space="preserve">Saisir le chemin d'installation de l'outil diff/merge</x:String>
<x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">Outil</x:String>
<x:String x:Key="Text.PruneRemote" xml:space="preserve">Élaguer une branche distant</x:String> <!-- If it is indeed about a branch -->
<x:String x:Key="Text.PruneRemote.Target" xml:space="preserve">Cible :</x:String>
<x:String x:Key="Text.PruneWorktrees" xml:space="preserve">Élaguer les Worktrees</x:String>
<x:String x:Key="Text.PruneWorktrees.Tip" xml:space="preserve"> Élaguer les information de worktree dans `$GIT_DIR/worktrees`</x:String>
<x:String x:Key="Text.Pull" xml:space="preserve">Pull</x:String>
<x:String x:Key="Text.Pull.Branch" xml:space="preserve">Branche :</x:String>
<x:String x:Key="Text.Pull.FetchAllBranches" xml:space="preserve">Fetch toutes les branches</x:String>
<x:String x:Key="Text.Pull.Into" xml:space="preserve">Dans :</x:String>
<x:String x:Key="Text.Pull.LocalChanges" xml:space="preserve">Changements locaux :</x:String>
<x:String x:Key="Text.Pull.LocalChanges.Discard" xml:space="preserve">Rejeter</x:String>
<x:String x:Key="Text.Pull.LocalChanges.DoNothing" xml:space="preserve">Ne rien faire</x:String>
<x:String x:Key="Text.Pull.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Réappliquer</x:String>
<x:String x:Key="Text.Pull.NoTags" xml:space="preserve">Fetch sans les tags</x:String>
<x:String x:Key="Text.Pull.Remote" xml:space="preserve">Distant :</x:String> <!-- Branch ?-->
<x:String x:Key="Text.Pull.Title" xml:space="preserve">Pull (Fetch &amp; Merge)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">Use rebase instead of merge</x:String>
<x:String x:Key="Text.Push" xml:space="preserve">Push</x:String>
<x:String x:Key="Text.Push.CheckSubmodules" xml:space="preserve">Make sure submodules have been pushed</x:String>
<x:String x:Key="Text.Push.Force" xml:space="preserve">Force push</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">Local Branch:</x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Push.Title" xml:space="preserve">Push Changes To Remote</x:String>
<x:String x:Key="Text.Push.To" xml:space="preserve">Remote Branch:</x:String>
<x:String x:Key="Text.Push.Tracking" xml:space="preserve">Set as tracking branch</x:String>
<x:String x:Key="Text.Push.WithAllTags" xml:space="preserve">Push all tags</x:String>
<x:String x:Key="Text.PushTag" xml:space="preserve">Push Tag To Remote</x:String>
<x:String x:Key="Text.PushTag.PushAllRemotes" xml:space="preserve">Push to all remotes</x:String>
<x:String x:Key="Text.PushTag.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.PushTag.Tag" xml:space="preserve">Tag:</x:String>
<x:String x:Key="Text.Quit" xml:space="preserve">Quit</x:String>
<x:String x:Key="Text.Rebase" xml:space="preserve">Rebase Current Branch</x:String>
<x:String x:Key="Text.Rebase.AutoStash" xml:space="preserve">Stash &amp; reapply local changes</x:String>
<x:String x:Key="Text.Rebase.On" xml:space="preserve">On:</x:String>
<x:String x:Key="Text.Rebase.Target" xml:space="preserve">Rebase:</x:String>
<x:String x:Key="Text.RefetchAvatar" xml:space="preserve">Refresh</x:String>
<x:String x:Key="Text.Remote.AddTitle" xml:space="preserve">Add Remote</x:String>
<x:String x:Key="Text.Remote.EditTitle" xml:space="preserve">Edit Remote</x:String>
<x:String x:Key="Text.Remote.Name" xml:space="preserve">Name:</x:String>
<x:String x:Key="Text.Remote.Name.Placeholder" xml:space="preserve">Remote name</x:String>
<x:String x:Key="Text.Remote.URL" xml:space="preserve">Repository URL:</x:String>
<x:String x:Key="Text.Remote.URL.Placeholder" xml:space="preserve">Remote git repository URL</x:String>
<x:String x:Key="Text.RemoteCM.CopyURL" xml:space="preserve">Copy URL</x:String>
<x:String x:Key="Text.RemoteCM.Delete" xml:space="preserve">Delete...</x:String>
<x:String x:Key="Text.RemoteCM.Edit" xml:space="preserve">Edit...</x:String>
<x:String x:Key="Text.RemoteCM.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.RemoteCM.OpenInBrowser" xml:space="preserve">Open In Browser</x:String>
<x:String x:Key="Text.RemoteCM.Prune" xml:space="preserve">Prune</x:String>
<x:String x:Key="Text.RemoteCM.Prune.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.RemoveWorktree" xml:space="preserve">Confirm to Remove Worktree</x:String>
<x:String x:Key="Text.RemoveWorktree.Force" xml:space="preserve">Enable `--force` Option</x:String>
<x:String x:Key="Text.RemoveWorktree.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.RenameBranch" xml:space="preserve">Rename Branch</x:String>
<x:String x:Key="Text.RenameBranch.Name" xml:space="preserve">New Name:</x:String>
<x:String x:Key="Text.RenameBranch.Name.Placeholder" xml:space="preserve">Unique name for this branch</x:String>
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORT</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Cleanup(GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Run `git gc` command for this repository.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Ouvrir dans l'explorateur Windows</x:String>
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">FILTERED BY:</x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOCAL BRANCHES</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate To HEAD</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Enable '--first-parent' Option</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Open In {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open In External Tools</x:String>
<x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Refresh</x:String>
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String>
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADD REMOTE</x:String>
<x:String x:Key="Text.Repository.Resolve" xml:space="preserve">RESOLVE</x:String>
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Search Commit</x:String>
<x:String x:Key="Text.Repository.Search.By" xml:space="preserve">Search By</x:String>
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">File</x:String>
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Message</x:String>
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.Repository.Search.ByUser" xml:space="preserve">Author &amp; Committer</x:String>
<x:String x:Key="Text.Repository.SearchBranchTag" xml:space="preserve">Search Branches &amp; Tags</x:String>
<x:String x:Key="Text.Repository.ShowTagsAsTree" xml:space="preserve">Show Tags as Tree</x:String>
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Statistics</x:String>
<x:String x:Key="Text.Repository.Submodules" xml:space="preserve">SUBMODULES</x:String>
<x:String x:Key="Text.Repository.Submodules.Add" xml:space="preserve">ADD SUBMODULE</x:String>
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">UPDATE SUBMODULE</x:String>
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEW TAG</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Ouvrir dans un terminal</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ADD WORKTREE</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>
<x:String x:Key="Text.RepositoryURL" xml:space="preserve">Git Repository URL</x:String>
<x:String x:Key="Text.Reset" xml:space="preserve">Reset Current Branch To Revision</x:String>
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Reset Mode:</x:String>
<x:String x:Key="Text.Reset.MoveTo" xml:space="preserve">Move To:</x:String>
<x:String x:Key="Text.Reset.Target" xml:space="preserve">Current Branch:</x:String>
<x:String x:Key="Text.RevealFile" xml:space="preserve">Reveal in File Explorer</x:String>
<x:String x:Key="Text.Revert" xml:space="preserve">Revert Commit</x:String>
<x:String x:Key="Text.Revert.Commit" xml:space="preserve">Commit:</x:String>
<x:String x:Key="Text.Revert.CommitChanges" xml:space="preserve">Commit revert changes</x:String>
<x:String x:Key="Text.Reword" xml:space="preserve">Reword Commit Message</x:String>
<x:String x:Key="Text.Reword.Tip" xml:space="preserve">Use 'Shift+Enter' to input a new line. 'Enter' is the hotkey of OK button</x:String>
<x:String x:Key="Text.Running" xml:space="preserve">Running. Please wait...</x:String>
<x:String x:Key="Text.Save" xml:space="preserve">SAVE</x:String>
<x:String x:Key="Text.SaveAs" xml:space="preserve">Save As...</x:String>
<x:String x:Key="Text.SaveAsPatchSuccess" xml:space="preserve">Patch has been saved successfully!</x:String>
<x:String x:Key="Text.SelfUpdate" xml:space="preserve">Vérifier les mises à jour...</x:String>
<x:String x:Key="Text.SelfUpdate.Available" xml:space="preserve">Une nouvelle version du logiciel est disponible :</x:String>
<x:String x:Key="Text.SelfUpdate.Error" xml:space="preserve">La vérification de mise à jour à échouée !</x:String>
<x:String x:Key="Text.SelfUpdate.GotoDownload" xml:space="preserve">Télécharger</x:String>
<x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Passer cette version</x:String>
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Mise à jour du logiciel</x:String>
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">Il n'y a pas de mise à jour pour le moment.</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Squash Commits</x:String>
<x:String x:Key="Text.SSHKey" xml:space="preserve">SSH Private Key:</x:String>
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Private SSH key store path</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">START</x:String>
<x:String x:Key="Text.Stash" xml:space="preserve">Stash</x:String>
<x:String x:Key="Text.Stash.IncludeUntracked" xml:space="preserve">Include untracked files</x:String>
<x:String x:Key="Text.Stash.Message" xml:space="preserve">Message:</x:String>
<x:String x:Key="Text.Stash.Message.Placeholder" xml:space="preserve">Optional. Name of this stash</x:String>
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Stash Local Changes</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Apply</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Drop</x:String>
<x:String x:Key="Text.StashCM.Pop" xml:space="preserve">Pop</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Drop Stash</x:String>
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Drop:</x:String>
<x:String x:Key="Text.Stashes" xml:space="preserve">Stashes</x:String>
<x:String x:Key="Text.Stashes.Changes" xml:space="preserve">CHANGES</x:String>
<x:String x:Key="Text.Stashes.Stashes" xml:space="preserve">STASHES</x:String>
<x:String x:Key="Text.Statistics" xml:space="preserve">Statistics</x:String>
<x:String x:Key="Text.Statistics.CommitAmount" xml:space="preserve">COMMITS</x:String>
<x:String x:Key="Text.Statistics.Committer" xml:space="preserve">COMMITTER</x:String>
<x:String x:Key="Text.Statistics.ThisMonth" xml:space="preserve">MONTH</x:String>
<x:String x:Key="Text.Statistics.ThisWeek" xml:space="preserve">WEEK</x:String>
<x:String x:Key="Text.Statistics.ThisYear" xml:space="preserve">YEAR</x:String>
<x:String x:Key="Text.Statistics.TotalCommits" xml:space="preserve">COMMITS: </x:String>
<x:String x:Key="Text.Statistics.TotalCommitters" xml:space="preserve">COMMITTERS: </x:String>
<x:String x:Key="Text.Submodule" xml:space="preserve">SUBMODULES</x:String>
<x:String x:Key="Text.Submodule.Add" xml:space="preserve">Add Submodule</x:String>
<x:String x:Key="Text.Submodule.CopyPath" xml:space="preserve">Copy Relative Path</x:String>
<x:String x:Key="Text.Submodule.FetchNested" xml:space="preserve">Fetch nested submodules</x:String>
<x:String x:Key="Text.Submodule.Open" xml:space="preserve">Open Submodule Repository</x:String>
<x:String x:Key="Text.Submodule.RelativePath" xml:space="preserve">Relative Path:</x:String>
<x:String x:Key="Text.Submodule.RelativePath.Placeholder" xml:space="preserve">Relative folder to store this module.</x:String>
<x:String x:Key="Text.Submodule.Remove" xml:space="preserve">Delete Submodule</x:String>
<x:String x:Key="Text.Sure" xml:space="preserve">OK</x:String>
<x:String x:Key="Text.TagCM.Copy" xml:space="preserve">Copy Tag Name</x:String>
<x:String x:Key="Text.TagCM.Delete" xml:space="preserve">Delete ${0}$...</x:String>
<x:String x:Key="Text.TagCM.Push" xml:space="preserve">Push ${0}$...</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">URL:</x:String>
<x:String x:Key="Text.UpdateSubmodules" xml:space="preserve">Update Submodules</x:String>
<x:String x:Key="Text.UpdateSubmodules.All" xml:space="preserve">All submodules</x:String>
<x:String x:Key="Text.UpdateSubmodules.Init" xml:space="preserve">Initialize as needed</x:String>
<x:String x:Key="Text.UpdateSubmodules.Recursive" xml:space="preserve">Recursively</x:String>
<x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Submodule:</x:String>
<x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Use --remote option</x:String>
<x:String x:Key="Text.Warn" xml:space="preserve">Warning</x:String>
<x:String x:Key="Text.Welcome" xml:space="preserve">Page d'accueil</x:String>
<x:String x:Key="Text.Welcome.AddRootFolder" xml:space="preserve">Créer un groupe</x:String>
<x:String x:Key="Text.Welcome.AddSubFolder" xml:space="preserve">Créer un sous-groupe</x:String>
<x:String x:Key="Text.Welcome.Clone" xml:space="preserve">Cloner un dépôt</x:String>
<x:String x:Key="Text.Welcome.Delete" xml:space="preserve">Supprimer</x:String>
<x:String x:Key="Text.Welcome.DragDropTip" xml:space="preserve">GLISSER / DEPOSER DE DOSSIER SUPPORTÉ. GROUPAGE PERSONNALISÉ SUPPORTÉ.</x:String>
<x:String x:Key="Text.Welcome.Edit" xml:space="preserve">Éditer</x:String>
<x:String x:Key="Text.Welcome.OpenAllInNode" xml:space="preserve">Ouvrir tous les dépôts</x:String>
<x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">Ouvrir un dépôt</x:String>
<x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">Ouvrir le terminal</x:String>
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">Chercher des dépôts...</x:String>
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">Trier</x:String>
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">Changes</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Git Ignore</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignore all *{0} files</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignore *{0} files in the same folder</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignore files in the same folder</x:String>
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignore this file only</x:String>
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String>
<x:String x:Key="Text.WorkingCopy.AutoStage" xml:space="preserve">Auto-Stage</x:String>
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">You can stage this file now.</x:String>
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
<x:String x:Key="Text.WorkingCopy.CommitAndPush" xml:space="preserve">COMMIT &amp; PUSH</x:String>
<x:String x:Key="Text.WorkingCopy.CommitMessageHelper" xml:space="preserve">Template/Histories</x:String>
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">CTRL + Enter</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">CONFLICTS DETECTED</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">FILE CONFLICTS ARE RESOLVED</x:String>
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">INCLUDE UNTRACKED FILES</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">NO RECENT INPUT MESSAGES</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">NO COMMIT TEMPLATES</x:String>
<x:String x:Key="Text.WorkingCopy.Staged" xml:space="preserve">STAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Staged.Unstage" xml:space="preserve">UNSTAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Staged.UnstageAll" xml:space="preserve">UNSTAGE ALL</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged" xml:space="preserve">UNSTAGED</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.Stage" xml:space="preserve">STAGE</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.StageAll" xml:space="preserve">STAGE ALL</x:String>
<x:String x:Key="Text.WorkingCopy.Unstaged.ViewAssumeUnchaged" xml:space="preserve">VIEW ASSUME UNCHANGED</x:String>
<x:String x:Key="Text.WorkingCopy.UseCommitTemplate" xml:space="preserve">Template: ${0}$</x:String>
<x:String x:Key="Text.WorkingCopy.ResolveTip" xml:space="preserve">Right-click the selected file(s), and make your choice to resolve conflicts.</x:String>
<x:String x:Key="Text.Worktree" xml:space="preserve">WORKTREE</x:String>
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Copy Path</x:String>
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">Lock</x:String>
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">Remove</x:String>
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">Unlock</x:String>
</ResourceDictionary>

View file

@ -382,14 +382,13 @@
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">Usar apenas fonte monoespaçada no editor de texto</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">Tema</x:String>
<x:String x:Key="Text.Preference.Appearance.ThemeOverrides" xml:space="preserve">Sobrescrever Tema</x:String>
<x:String x:Key="Text.Preference.Appearance.UseFixedTabWidth" xml:space="preserve">Usar largura fixa da aba na barra de título</x:String>
<x:String x:Key="Text.Preference.General" xml:space="preserve">GERAL</x:String>
<x:String x:Key="Text.Preference.General.Check4UpdatesOnStartup" xml:space="preserve">Verificar atualizações na inicialização</x:String>
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Idioma</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">Commits do Histórico</x:String>
<x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">Restaurar as últimas abas abertas na inicialização</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">Comprimento do Guia de Assunto</x:String>
<x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">Usar largura fixa da aba na barra de título</x:String>
<x:String x:Key="Text.Preference.General.VisibleDiffContextLines" xml:space="preserve">Linhas de Contexto de Diferença Visíveis</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">Buscar remotos automaticamente</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">Intervalo de Busca Automática</x:String>
@ -480,6 +479,7 @@
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">FILTRADO POR:</x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">BRANCHES LOCAIS</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navegar para HEAD</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">Filtro do Primeiro Pai</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Criar Branch</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">Abrir em {0}</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Abrir em Ferramentas Externas</x:String>
@ -527,7 +527,7 @@
<x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">Ignorar esta versão</x:String>
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">Atualização de Software</x:String>
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">Não há atualizações disponíveis no momento.</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Unir HEAD ao Parent</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">Squash Commits</x:String>
<x:String x:Key="Text.SSHKey" xml:space="preserve">Chave SSH Privada:</x:String>
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">Caminho para a chave SSH privada</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">INICIAR</x:String>

View file

@ -110,6 +110,7 @@
<x:String x:Key="Text.CommitCM.Reword" xml:space="preserve">编辑提交信息</x:String>
<x:String x:Key="Text.CommitCM.SaveAsPatch" xml:space="preserve">另存为补丁 ...</x:String>
<x:String x:Key="Text.CommitCM.Squash" xml:space="preserve">合并此提交到上一个提交</x:String>
<x:String x:Key="Text.CommitCM.SquashCommitsSinceThis" xml:space="preserve">合并之后的提交到此处</x:String>
<x:String x:Key="Text.CommitDetail.Changes" xml:space="preserve">变更对比</x:String>
<x:String x:Key="Text.CommitDetail.Changes.Search" xml:space="preserve">查找变更...</x:String>
<x:String x:Key="Text.CommitDetail.Files" xml:space="preserve">文件列表</x:String>
@ -119,6 +120,8 @@
<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.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>
<x:String x:Key="Text.CommitDetail.Info.Message" xml:space="preserve">提交信息</x:String>
<x:String x:Key="Text.CommitDetail.Info.Parents" xml:space="preserve">父提交</x:String>
@ -146,6 +149,7 @@
<x:String x:Key="Text.Configure.User" xml:space="preserve">用户名</x:String>
<x:String x:Key="Text.Configure.User.Placeholder" xml:space="preserve">应用于本仓库的用户名</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">复制</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">复制全部文本</x:String>
<x:String x:Key="Text.CopyMessage" xml:space="preserve">复制内容</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">复制路径</x:String>
<x:String x:Key="Text.CopyFileName" xml:space="preserve">复制文件名</x:String>
@ -244,6 +248,8 @@
<x:String x:Key="Text.FileCM.UseTheirs" xml:space="preserve">使用 THEIRS (checkout --theirs)</x:String>
<x:String x:Key="Text.FileCM.UseMine" xml:space="preserve">使用 MINE (checkout --ours)</x:String>
<x:String x:Key="Text.FileHistory" xml:space="preserve">文件历史</x:String>
<x:String x:Key="Text.FileHistory.FileContent" xml:space="preserve">文件内容</x:String>
<x:String x:Key="Text.FileHistory.FileChange" xml:space="preserve">文件变更</x:String>
<x:String x:Key="Text.Filter" xml:space="preserve">过滤</x:String>
<x:String x:Key="Text.GitFlow" xml:space="preserve">GIT工作流</x:String>
<x:String x:Key="Text.GitFlow.DevelopBranch" xml:space="preserve">开发分支 </x:String>
@ -382,14 +388,14 @@
<x:String x:Key="Text.Preference.Appearance.OnlyUseMonoFontInEditor" xml:space="preserve">仅在文本编辑器中使用等宽字体</x:String>
<x:String x:Key="Text.Preference.Appearance.Theme" xml:space="preserve">主题</x:String>
<x:String x:Key="Text.Preference.Appearance.ThemeOverrides" xml:space="preserve">主题自定义</x:String>
<x:String x:Key="Text.Preference.Appearance.UseFixedTabWidth" xml:space="preserve">主标签使用固定宽度</x:String>
<x:String x:Key="Text.Preference.Appearance.UseNativeWindowFrame" xml:space="preserve">使用系统默认窗体样式</x:String>
<x:String x:Key="Text.Preference.General" xml:space="preserve">通用配置</x:String>
<x:String x:Key="Text.Preference.General.Check4UpdatesOnStartup" xml:space="preserve">启动时检测软件更新</x:String>
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">显示语言</x:String>
<x:String x:Key="Text.Preference.General.MaxHistoryCommits" xml:space="preserve">最大历史提交数</x:String>
<x:String x:Key="Text.Preference.General.RestoreTabs" xml:space="preserve">启动时恢复上次打开的仓库</x:String>
<x:String x:Key="Text.Preference.General.SubjectGuideLength" xml:space="preserve">SUBJECT字数检测</x:String>
<x:String x:Key="Text.Preference.General.UseFixedTabWidth" xml:space="preserve">使用固定宽度的标题栏标签</x:String>
<x:String x:Key="Text.Preference.General.VisibleDiffContextLines" xml:space="preserve">DIFF上下文行数</x:String>
<x:String x:Key="Text.Preference.Git" xml:space="preserve">GIT配置</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetch" xml:space="preserve">启用定时自动拉取远程更新</x:String>
<x:String x:Key="Text.Preference.Git.AutoFetchInterval" xml:space="preserve">自动拉取间隔</x:String>
@ -433,6 +439,7 @@
<x:String x:Key="Text.Pull.Title" xml:space="preserve">拉回(拉取并合并)</x:String>
<x:String x:Key="Text.Pull.UseRebase" xml:space="preserve">使用变基方式合并分支</x:String>
<x:String x:Key="Text.Push" xml:space="preserve">推送(push)</x:String>
<x:String x:Key="Text.Push.CheckSubmodules" xml:space="preserve">确保子模块变更已推送</x:String>
<x:String x:Key="Text.Push.Force" xml:space="preserve">启用强制推送</x:String>
<x:String x:Key="Text.Push.Local" xml:space="preserve">本地分支 </x:String>
<x:String x:Key="Text.Push.Remote" xml:space="preserve">远程仓库 </x:String>
@ -479,6 +486,7 @@
<x:String x:Key="Text.Repository.FilterCommitPrefix" xml:space="preserve">过滤规则 </x:String>
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">本地分支</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">定位HEAD</x:String>
<x:String x:Key="Text.Repository.FirstParentFilterToggle" xml:space="preserve">启用 --first-parent 过滤选项</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String>
<x:String x:Key="Text.Repository.OpenIn" xml:space="preserve">在 {0} 中打开</x:String>
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">使用外部工具打开</x:String>
@ -526,7 +534,8 @@
<x:String x:Key="Text.SelfUpdate.IgnoreThisVersion" xml:space="preserve">忽略此版本</x:String>
<x:String x:Key="Text.SelfUpdate.Title" xml:space="preserve">软件更新</x:String>
<x:String x:Key="Text.SelfUpdate.UpToDate" xml:space="preserve">当前已是最新版本。</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">合并HEAD到上一个提交</x:String>
<x:String x:Key="Text.Squash" xml:space="preserve">压缩为单个提交</x:String>
<x:String x:Key="Text.Squash.Into" xml:space="preserve">合并入:</x:String>
<x:String x:Key="Text.SSHKey" xml:space="preserve">SSH密钥 </x:String>
<x:String x:Key="Text.SSHKey.Placeholder" xml:space="preserve">SSH密钥文件</x:String>
<x:String x:Key="Text.Start" xml:space="preserve">开 始</x:String>

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="using:SourceGit"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:c="using:SourceGit.Converters"
xmlns:ae="using:AvaloniaEdit"
@ -22,8 +23,6 @@
<Setter Property="Background" Value="{DynamicResource Brush.Window}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/>
<Setter Property="ExtendClientAreaChromeHints" Value="NoChrome"/>
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True"/>
<Setter Property="SystemDecorations" Value="Full"/>
<Setter Property="Padding" Value="0"/>
@ -47,6 +46,7 @@
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="SystemDecorations" Value="None"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Template">
<ControlTemplate>
@ -120,9 +120,9 @@
Background="{DynamicResource Brush.Window}"
BorderBrush="{DynamicResource Brush.WindowBorder}"
BorderThickness="1"
CornerRadius="8">
CornerRadius="{TemplateBinding CornerRadius}">
<VisualLayerManager>
<Border CornerRadius="8" ClipToBounds="True">
<Border CornerRadius="{TemplateBinding CornerRadius}" ClipToBounds="True">
<ContentPresenter Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
@ -139,6 +139,7 @@
<Style Selector="Window.custom_window_frame[WindowState=Maximized]">
<Setter Property="Padding" Value="0"/>
<Setter Property="CornerRadius" Value="0"/>
</Style>
<Style Selector="Window.custom_window_frame[WindowState=Maximized] /template/ Border#PART_ContentRoot">
@ -156,7 +157,7 @@
</Style>
<Style Selector="ContentPresenter">
<Setter Property="FontFamily" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFont}"/>
<Setter Property="FontFamily" Value="{DynamicResource Fonts.Default}"/>
<Setter Property="FontSize" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize}"/>
</Style>
@ -192,9 +193,6 @@
<Setter Property="MaxHeight" Value="768"/>
</Style>
<Style Selector="Grid.repository_leftpanel">
</Style>
<Style Selector="Path">
<Setter Property="Fill" Value="{DynamicResource Brush.FG1}"/>
<Setter Property="Stretch" Value="Uniform"/>
@ -251,7 +249,7 @@
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
<Setter Property="FontFamily" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFont}"/>
<Setter Property="FontFamily" Value="{DynamicResource Fonts.Default}"/>
<Setter Property="FontSize" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize}"/>
</Style>
<Style Selector="TextBlock.small">
@ -264,7 +262,7 @@
<Setter Property="FontStyle" Value="Italic"/>
</Style>
<Style Selector="TextBlock.primary, SelectableTextBlock.primary">
<Setter Property="FontFamily" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=PrimaryFont}"/>
<Setter Property="FontFamily" Value="{DynamicResource Fonts.Primary}"/>
</Style>
<Style Selector="TextBlock.group_header_label">
<Setter Property="Foreground" Value="{DynamicResource Brush.FG2}"/>
@ -285,6 +283,10 @@
<Style Selector="Run.issue_link">
<Setter Property="Foreground" Value="{DynamicResource Brush.Link}"/>
</Style>
<Style Selector="Run.commit_link">
<Setter Property="Foreground" Value="DarkOrange"/>
<Setter Property="TextDecorations" Value="Underline"/>
</Style>
<Style Selector="SelectableTextBlock">
<Setter Property="HorizontalAlignment" Value="Left"/>
@ -303,6 +305,14 @@
<Path Width="11" Height="11" Data="{StaticResource Icons.Copy}" VerticalAlignment="Center"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="{DynamicResource Text.CopyAllText}"
Command="{x:Static s:App.CopyTextCommand}"
CommandParameter="{Binding $parent[SelectableTextBlock]}">
<MenuItem.Icon>
<Path Width="11" Height="11" Data="{StaticResource Icons.Copy}" VerticalAlignment="Center"/>
</MenuItem.Icon>
</MenuItem>
</MenuFlyout>
</Setter.Value>
</Setter>
@ -518,6 +528,9 @@
<Style Selector="Button.flat.primary TextBlock">
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForeground}"/>
</Style>
<Style Selector="Button.flat.primary ToolTip TextBlock">
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
</Style>
<Style Selector="aes|SearchPanel">
<Setter Property="Template">
@ -530,28 +543,10 @@
HorizontalAlignment="Right"
VerticalAlignment="Top"
Padding="10">
<Grid ColumnDefinitions="Auto,Auto,Auto"
RowDefinitions="Auto,Auto,Auto">
<ToggleButton Name="Expander"
Theme="{StaticResource SearchPanelExpanderToggle}"
VerticalAlignment="Center"
IsVisible="{Binding !TextEditor.IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}"
IsChecked="{Binding IsReplaceMode, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Grid.Column="0"
Grid.Row="0"
Width="16"
Margin="0, 0, 5, 0">
<ToolTip.Tip>
<TextBlock Text="{x:Static ae:SR.SearchToggleReplace}" />
</ToolTip.Tip>
</ToggleButton>
<StackPanel Orientation="Horizontal"
Grid.Column="2"
Grid.Row="0">
<Grid RowDefinitions="Auto,Auto">
<StackPanel Grid.Row="0" Orientation="Horizontal">
<TextBox Watermark="{x:Static ae:SR.SearchLabel}"
Name="PART_searchTextBox"
Grid.Column="1"
Grid.Row="0"
Width="265" Height="28"
Margin="0,0,0,0"
CornerRadius="2"
@ -560,39 +555,24 @@
<StackPanel Orientation="Horizontal">
<ToggleButton Theme="{StaticResource SearchPanelTextBoxButton}"
IsChecked="{Binding $parent[aes:SearchPanel].MatchCase, Mode=TwoWay}"
ToolTip.Tip="{x:Static ae:SR.SearchMatchCaseText}"
ToolTip.Tip="Match case"
Width="24" Height="20"
VerticalAlignment="Center">
<Path Data="{StaticResource CaseSensitiveIconPath}"
Stretch="Uniform"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="12"
Fill="{DynamicResource Brush.FG1}"/>
<Path Width="12" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Data="{StaticResource CaseSensitiveIconPath}" Fill="{DynamicResource Brush.FG1}"/>
</ToggleButton>
<ToggleButton Theme="{StaticResource SearchPanelTextBoxButton}"
IsChecked="{Binding $parent[aes:SearchPanel].WholeWords, Mode=TwoWay}"
ToolTip.Tip="{x:Static ae:SR.SearchMatchWholeWordsText}"
ToolTip.Tip="Match whole words"
Margin="3,0,0,0" Width="24" Height="20"
VerticalAlignment="Center">
<Path Data="{StaticResource CompleteWordIconPath}"
Stretch="Uniform"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="14"
Fill="{DynamicResource Brush.FG1}"/>
<Path Width="14" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Data="{StaticResource CompleteWordIconPath}" Fill="{DynamicResource Brush.FG1}"/>
</ToggleButton>
<ToggleButton Theme="{StaticResource SearchPanelTextBoxButton}"
IsChecked="{Binding $parent[aes:SearchPanel].UseRegex, Mode=TwoWay}"
ToolTip.Tip="{x:Static ae:SR.SearchUseRegexText}"
ToolTip.Tip="Use regular expressions"
Margin="3,0,5,0" Width="24" Height="20"
VerticalAlignment="Center">
<Path Data="{StaticResource RegularExpressionIconPath}"
Stretch="Uniform"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="12"
Fill="{DynamicResource Brush.FG1}"/>
<Path Width="12" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Data="{StaticResource RegularExpressionIconPath}" Fill="{DynamicResource Brush.FG1}"/>
</ToggleButton>
</StackPanel>
</TextBox.InnerRightContent>
@ -601,84 +581,20 @@
Width="28"
Background="Transparent"
VerticalAlignment="Stretch"
Command="{x:Static aes:SearchCommands.FindPrevious}">
<ToolTip.Tip>
<TextBlock Text="{x:Static ae:SR.SearchFindPreviousText}" />
</ToolTip.Tip>
<Path Data="{StaticResource Icons.Up}"
Stretch="Uniform"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="14"
Fill="{DynamicResource Brush.FG1}"/>
Command="{x:Static aes:SearchCommands.FindPrevious}"
ToolTip.Tip="Find Previous (Shift+F3)">
<Path Width="14" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Data="{StaticResource Icons.Up}" Fill="{DynamicResource Brush.FG1}"/>
</Button>
<Button Margin="3,0,0,0"
VerticalAlignment="Stretch"
Width="28"
Background="Transparent"
Command="{x:Static aes:SearchCommands.FindNext}">
<ToolTip.Tip>
<TextBlock Text="{x:Static ae:SR.SearchFindNextText}" />
</ToolTip.Tip>
<Path Data="{StaticResource Icons.Down}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"
Width="14"
Fill="{DynamicResource Brush.FG1}"/>
Command="{x:Static aes:SearchCommands.FindNext}"
ToolTip.Tip="Find Next (F3)">
<Path Width="14" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Data="{StaticResource Icons.Down}" Fill="{DynamicResource Brush.FG1}"/>
</Button>
</StackPanel>
<StackPanel Name="ReplaceButtons"
IsVisible="{Binding #Expander.IsChecked}"
Orientation="Horizontal"
Margin="0 5 0 0 "
Grid.Column="2"
Grid.Row="1">
<TextBox Name="ReplaceBox" Watermark="{x:Static ae:SR.ReplaceLabel}"
IsVisible="{Binding IsReplaceMode, RelativeSource={RelativeSource TemplatedParent}}"
Grid.Column="1"
Grid.Row="1"
Width="265" Height="28"
Margin="0 0 0 0"
CornerRadius="2"
Text="{Binding ReplacePattern, RelativeSource={RelativeSource TemplatedParent}}" />
<Button Margin="5, 0, 0, 0"
VerticalAlignment="Stretch"
Width="28"
Background="Transparent"
Command="{x:Static aes:SearchCommands.ReplaceNext}">
<ToolTip.Tip>
<TextBlock Text="{x:Static ae:SR.SearchReplaceNext}" />
</ToolTip.Tip>
<Path Data="{StaticResource ReplaceNextIconPath}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"
Width="12"
Fill="{DynamicResource Brush.FG1}"/>
</Button>
<Button Margin="3, 0, 0, 0"
VerticalAlignment="Stretch"
Width="28"
Background="Transparent"
Command="{x:Static aes:SearchCommands.ReplaceAll}">
<ToolTip.Tip>
<TextBlock Text="{x:Static ae:SR.SearchReplaceAll}" />
</ToolTip.Tip>
<Path Data="{StaticResource ReplaceAllIconPath}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"
Width="18"
Fill="{DynamicResource Brush.FG1}" />
</Button>
</StackPanel>
<StackPanel Name="PART_MessageView"
IsVisible="False"
Orientation="Horizontal"
Margin="0 5 0 0"
Grid.Column="2"
Grid.Row="2">
<StackPanel Grid.Row="1" Name="PART_MessageView" IsVisible="False" Orientation="Horizontal" Margin="0 5 0 0">
<TextBlock Name="PART_MessageContent" FontSize="11" />
</StackPanel>
</Grid>
@ -706,6 +622,57 @@
<Setter Property="Opacity" Value="1"/>
</Style>
<Style Selector="ListBox.repo_left_content_list">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ItemsPanel">
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</Setter>
<Style Selector="^ ListBoxItem">
<Setter Property="Height" Value="24"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<ControlTemplate>
<Grid>
<Border Name="PART_Background"
Background="Transparent"
CornerRadius="{TemplateBinding CornerRadius}"
Opacity="0"/>
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Stretch" />
</Grid>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="^ ListBoxItem:pointerover /template/ Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}" />
<Setter Property="Opacity" Value=".5"/>
</Style>
<Style Selector="^ ListBoxItem:selected /template/ Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}" />
<Setter Property="Opacity" Value="1"/>
</Style>
<Style Selector="^:focus-within ListBoxItem:selected /template/ Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".65"/>
</Style>
<Style Selector="^:focus-within ListBoxItem:selected:pointerover /template/ Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".8"/>
</Style>
</Style>
<Style Selector="ContextMenu">
<Setter Property="HorizontalOffset" Value="-4"/>
<Setter Property="VerticalOffset" Value="-4"/>
@ -748,7 +715,7 @@
<Border Name="LayoutRoot"
Margin="4"
Background="{TemplateBinding Background}"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0"
Padding="4,2"
@ -772,6 +739,7 @@
<Setter Property="Height" Value="28"/>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}" />
<Setter Property="Cursor" Value="Arrow"/>
<Setter Property="Template">
<ControlTemplate>
@ -1088,6 +1056,7 @@
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Template">
<ControlTemplate>
<Border Background="Transparent">
<Path x:Name="PART_IndicatorIcon"
Width="12"
Data="{StaticResource Icons.Filter}"
@ -1095,6 +1064,7 @@
StrokeThickness="1"
Stroke="{DynamicResource Brush.FG2}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter>
</Style>
@ -1105,7 +1075,7 @@
<Setter Property="Fill" Value="{DynamicResource Brush.FG2}"/>
</Style>
<Style Selector="ToggleButton.filter:pointerover /template/ Path#PART_IndicatorIcon">
<Setter Property="Stroke" Value="{DynamicResource Brush.AccentHovered}"/>
<Setter Property="Stroke" Value="{DynamicResource Brush.Accent}"/>
</Style>
<Style Selector="ToggleButton.tree_expander">
<Setter Property="Margin" Value="0" />
@ -1342,72 +1312,6 @@
<Setter Property="IsVisible" Value="False"/>
</Style>
<Style Selector="TreeViewItem">
<Style.Resources>
<x:Double x:Key="TreeViewItemIndent">16</x:Double>
</Style.Resources>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="MinHeight" Value="24" />
<Setter Property="Template">
<ControlTemplate>
<StackPanel>
<Border Name="PART_LayoutRoot"
Background="Transparent"
BorderThickness="0"
CornerRadius="0"
MinHeight="{TemplateBinding MinHeight}"
TemplatedControl.IsTemplateFocusTarget="True">
<Grid>
<Border Name="PART_Background" CornerRadius="{TemplateBinding CornerRadius}" Background="Transparent"/>
<Grid Name="PART_Header" ColumnDefinitions="16,*" Margin="{TemplateBinding Level, Mode=OneWay, Converter={StaticResource TreeViewItemLeftMarginConverter}}">
<Panel Name="PART_ExpandCollapseChevronContainer">
<ToggleButton Name="PART_ExpandCollapseChevron"
Classes="tree_expander"
Focusable="False"
HorizontalAlignment="Center"
IsChecked="{TemplateBinding IsExpanded, Mode=TwoWay}"/>
</Panel>
<ContentPresenter Name="PART_HeaderPresenter"
Grid.Column="1"
Focusable="False"
Background="Transparent"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Margin="{TemplateBinding Padding}" />
</Grid>
</Grid>
</Border>
<ItemsPresenter Name="PART_ItemsPresenter"
IsVisible="{TemplateBinding IsExpanded}"
ItemsPanel="{TemplateBinding ItemsPanel}" />
</StackPanel>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ Border#PART_LayoutRoot:pointerover">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="^ /template/ Border#PART_LayoutRoot:pointerover Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}" />
</Style>
<Style Selector="^:selected /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style Selector="^:selected /template/ Border#PART_LayoutRoot Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".4"/>
</Style>
<Style Selector="^:selected /template/ Border#PART_LayoutRoot:pointerover Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".65"/>
</Style>
</Style>
<Style Selector="NumericUpDown">
<Style Selector="^ /template/ ButtonSpinner#PART_Spinner">
<Setter Property="MinHeight" Value="0"/>

View file

@ -13,11 +13,12 @@
<Color x:Key="Color.Contents">#FFFAFAFA</Color>
<Color x:Key="Color.Badge">#FFB0CEE8</Color>
<Color x:Key="Color.BadgeFG">#FF1F1F1F</Color>
<Color x:Key="Color.DecoratorIconBG">#FF6F6F6F</Color>
<Color x:Key="Color.DecoratorIcon">#FFF8F8F8</Color>
<Color x:Key="Color.DecoratorBranch">#FFFFB835</Color>
<Color x:Key="Color.DecoratorTag">#FF02C302</Color>
<Color x:Key="Color.DecoratorFG">Black</Color>
<Color x:Key="Color.DecoratorIconBG">#A0A0A0</Color>
<Color x:Key="Color.DecoratorIcon">White</Color>
<Color x:Key="Color.DecoratorBranch">#008585</Color>
<Color x:Key="Color.DecoratorHead">#0C0E21</Color>
<Color x:Key="Color.DecoratorTag">#79855f</Color>
<Color x:Key="Color.DecoratorFG">White</Color>
<Color x:Key="Color.Conflict">#FF836C2E</Color>
<Color x:Key="Color.ConflictForeground">#FFFFFFFF</Color>
<Color x:Key="Color.Border0">#FFCFCFCF</Color>
@ -50,7 +51,8 @@
<Color x:Key="Color.DecoratorIconBG">#FF505050</Color>
<Color x:Key="Color.DecoratorIcon">#FFF8F8F8</Color>
<Color x:Key="Color.DecoratorBranch">#FFFFB835</Color>
<Color x:Key="Color.DecoratorTag">#FF02C302</Color>
<Color x:Key="Color.DecoratorHead">#f4f1de</Color>
<Color x:Key="Color.DecoratorTag">#84c88a</Color>
<Color x:Key="Color.DecoratorFG">Black</Color>
<Color x:Key="Color.Conflict">#FFFAFAD2</Color>
<Color x:Key="Color.ConflictForeground">#FF252525</Color>
@ -84,6 +86,7 @@
<SolidColorBrush x:Key="Brush.DecoratorIconBG" Color="{DynamicResource Color.DecoratorIconBG}"/>
<SolidColorBrush x:Key="Brush.DecoratorIcon" Color="{DynamicResource Color.DecoratorIcon}"/>
<SolidColorBrush x:Key="Brush.DecoratorBranch" Color="{DynamicResource Color.DecoratorBranch}"/>
<SolidColorBrush x:Key="Brush.DecoratorHead" Color="{DynamicResource Color.DecoratorHead}"/>
<SolidColorBrush x:Key="Brush.DecoratorTag" Color="{DynamicResource Color.DecoratorTag}"/>
<SolidColorBrush x:Key="Brush.DecoratorFG" Color="{DynamicResource Color.DecoratorFG}"/>
<SolidColorBrush x:Key="Brush.Conflict" Color="{DynamicResource Color.Conflict}"/>
@ -103,4 +106,8 @@
<SolidColorBrush x:Key="Brush.Diff.AddedHighlight" Color="{DynamicResource Color.Diff.AddedHighlight}"/>
<SolidColorBrush x:Key="Brush.Diff.DeletedHighlight" Color="{DynamicResource Color.Diff.DeletedHighlight}"/>
<SolidColorBrush x:Key="Brush.Link" Color="{DynamicResource Color.Link}"/>
<FontFamily x:Key="Fonts.Default">$Default</FontFamily>
<FontFamily x:Key="Fonts.Monospace">fonts:SourceGit#JetBrains Mono,$Default</FontFamily>
<FontFamily x:Key="Fonts.Primary">fonts:SourceGit#JetBrains Mono,$Default</FontFamily>
</ResourceDictionary>

View file

@ -141,6 +141,7 @@ namespace SourceGit.ViewModels
}
}
Welcome.Instance.Refresh();
launcher.OpenRepositoryInTab(node, page);
});

View file

@ -141,6 +141,11 @@ namespace SourceGit.ViewModels
_repo?.NavigateToCommit(commitSHA);
}
public List<Models.Decorator> GetRefsContainsThisCommit()
{
return new Commands.QueryRefsContainsCommit(_repo.FullPath, _commit.SHA).Result();
}
public void ClearSearchChangeFilter()
{
SearchChangeFilter = string.Empty;
@ -380,12 +385,12 @@ namespace SourceGit.ViewModels
saveAs.IsEnabled = file.Type == Models.ObjectType.Blob;
saveAs.Click += async (_, ev) =>
{
var topLevel = App.GetTopLevel();
if (topLevel == null)
var storageProvider = App.GetStorageProvider();
if (storageProvider == null)
return;
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
var selected = await storageProvider.OpenFolderPickerAsync(options);
if (selected.Count == 1)
{
var saveTo = Path.Combine(selected[0].Path.LocalPath, Path.GetFileName(file.Path));
@ -460,14 +465,18 @@ namespace SourceGit.ViewModels
if (_commit == null)
return;
Task.Run(() =>
{
var fullMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result();
Dispatcher.UIThread.Invoke(() => FullMessage = fullMessage);
});
if (_cancelToken != null)
_cancelToken.Requested = true;
_cancelToken = new Commands.Command.CancelToken();
Task.Run(() =>
{
var fullMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, _commit.SHA).Result();
var parent = _commit.Parents.Count == 0 ? "4b825dc642cb6eb9a060e54bf8d69288fbee4904" : _commit.Parents[0];
var cmdChanges = new Commands.CompareRevisions(_repo.FullPath, parent, _commit.SHA) { Cancel = _cancelToken };
var changes = cmdChanges.Result();
@ -486,7 +495,6 @@ namespace SourceGit.ViewModels
{
Dispatcher.UIThread.Post(() =>
{
FullMessage = fullMessage;
Changes = changes;
VisibleChanges = visible;
});

View file

@ -29,6 +29,7 @@ namespace SourceGit.ViewModels
IsExpanded = false,
}, _parent);
Welcome.Instance.Refresh();
return null;
}

View file

@ -19,6 +19,7 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure()
{
Preference.Instance.RemoveNode(_node);
Welcome.Instance.Refresh();
return null;
}

View file

@ -41,6 +41,12 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _content, value);
}
public int UnifiedLines
{
get => _unifiedLines;
private set => SetProperty(ref _unifiedLines, value);
}
public DiffContext(string repo, Models.DiffOption option, DiffContext previous = null)
{
_repo = repo;
@ -50,6 +56,7 @@ namespace SourceGit.ViewModels
{
_isTextDiff = previous._isTextDiff;
_content = previous._content;
_unifiedLines = previous._unifiedLines;
}
if (string.IsNullOrEmpty(_option.OrgPath) || _option.OrgPath == "/dev/null")
@ -62,21 +69,15 @@ namespace SourceGit.ViewModels
public void IncrUnified()
{
var pref = Preference.Instance;
pref.DiffViewVisualLineNumbers = pref.DiffViewVisualLineNumbers + 1;
UnifiedLines = _unifiedLines + 1;
LoadDiffContent();
}
public void DecrUnified()
{
var pref = Preference.Instance;
var unified = pref.DiffViewVisualLineNumbers - 1;
if (pref.DiffViewVisualLineNumbers != unified)
{
pref.DiffViewVisualLineNumbers = unified;
UnifiedLines = Math.Max(4, _unifiedLines - 1);
LoadDiffContent();
}
}
public void OpenExternalMergeTool()
{
@ -87,10 +88,17 @@ namespace SourceGit.ViewModels
private void LoadDiffContent()
{
var unified = Preference.Instance.DiffViewVisualLineNumbers;
if (_option.Path.EndsWith('/'))
{
Content = null;
IsTextDiff = false;
IsLoading = false;
return;
}
Task.Run(() =>
{
var latest = new Commands.Diff(_repo, _option, unified).Result();
var latest = new Commands.Diff(_repo, _option, _unifiedLines).Result();
var rs = null as object;
if (latest.TextDiff != null)
@ -225,6 +233,7 @@ namespace SourceGit.ViewModels
private readonly Models.DiffOption _option = null;
private string _title;
private string _fileModeChange = string.Empty;
private int _unifiedLines = 4;
private bool _isLoading = true;
private bool _isTextDiff = false;
private object _content = null;

View file

@ -48,7 +48,10 @@ namespace SourceGit.ViewModels
_node.Bookmark = _bookmark;
if (needSort)
{
Preference.Instance.SortByRenamedNode(_node);
Welcome.Instance.Refresh();
}
return null;
}

View file

@ -1,11 +1,22 @@
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class FileHistories : ObservableObject
public class FileHistoriesRevisionFile(string path, object content)
{
public string Path { get; set; } = path;
public object Content { get; set; } = content;
}
public partial class FileHistories : ObservableObject
{
public bool IsLoading
{
@ -25,38 +36,30 @@ namespace SourceGit.ViewModels
set
{
if (SetProperty(ref _selectedCommit, value))
{
if (value == null)
{
DiffContext = null;
DetailContext.Commit = null;
}
else
{
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(value, _file), _diffContext);
DetailContext.Commit = value;
}
}
RefreshViewContent();
}
}
public DiffContext DiffContext
public int ViewMode
{
get => _diffContext;
set => SetProperty(ref _diffContext, value);
get => _viewMode;
set
{
if (SetProperty(ref _viewMode, value))
RefreshViewContent();
}
}
public CommitDetail DetailContext
public object ViewContent
{
get => _detailContext;
set => SetProperty(ref _detailContext, value);
get => _viewContent;
private set => SetProperty(ref _viewContent, value);
}
public FileHistories(Repository repo, string file)
{
_repo = repo;
_file = file;
_detailContext = new CommitDetail(repo);
Task.Run(() =>
{
@ -71,12 +74,127 @@ namespace SourceGit.ViewModels
});
}
public void NavigateToCommit(Models.Commit commit)
{
_repo.NavigateToCommit(commit.SHA);
}
public void ResetToSelectedRevision()
{
new Commands.Checkout(_repo.FullPath).FileWithRevision(_file, $"{_selectedCommit.SHA}");
}
private void RefreshViewContent()
{
if (_selectedCommit == null)
{
ViewContent = null;
return;
}
if (_viewMode == 0)
SetViewContentAsDiff();
else
SetViewContentAsRevisionFile();
}
private void SetViewContentAsRevisionFile()
{
var objs = new Commands.QueryRevisionObjects(_repo.FullPath, _selectedCommit.SHA, _file).Result();
if (objs.Count == 0)
{
ViewContent = new FileHistoriesRevisionFile(_file, null);
return;
}
var obj = objs[0];
switch (obj.Type)
{
case Models.ObjectType.Blob:
Task.Run(() =>
{
var isBinary = new Commands.IsBinary(_repo.FullPath, _selectedCommit.SHA, _file).Result();
if (isBinary)
{
var ext = Path.GetExtension(_file);
if (IMG_EXTS.Contains(ext))
{
var stream = Commands.QueryFileContent.Run(_repo.FullPath, _selectedCommit.SHA, _file);
var bitmap = stream.Length > 0 ? new Bitmap(stream) : null;
var image = new Models.RevisionImageFile() { Image = bitmap };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, image));
}
else
{
var size = new Commands.QueryFileSize(_repo.FullPath, _file, _selectedCommit.SHA).Result();
var binaryFile = new Models.RevisionBinaryFile() { Size = size };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, binaryFile));
}
return;
}
var contentStream = Commands.QueryFileContent.Run(_repo.FullPath, _selectedCommit.SHA, _file);
var content = new StreamReader(contentStream).ReadToEnd();
var matchLFS = REG_LFS_FORMAT().Match(content);
if (matchLFS.Success)
{
var lfs = new Models.RevisionLFSObject() { Object = new Models.LFSObject() };
lfs.Object.Oid = matchLFS.Groups[1].Value;
lfs.Object.Size = long.Parse(matchLFS.Groups[2].Value);
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, lfs));
}
else
{
var txt = new Models.RevisionTextFile() { FileName = obj.Path, Content = content };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, txt));
}
});
break;
case Models.ObjectType.Commit:
Task.Run(() =>
{
var submoduleRoot = Path.Combine(_repo.FullPath, _file);
var commit = new Commands.QuerySingleCommit(submoduleRoot, obj.SHA).Result();
if (commit != null)
{
var message = new Commands.QueryCommitFullMessage(submoduleRoot, obj.SHA).Result();
var module = new Models.RevisionSubmodule() { Commit = commit, FullMessage = message };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
}
else
{
var module = new Models.RevisionSubmodule() { Commit = new Models.Commit() { SHA = obj.SHA }, FullMessage = "" };
Dispatcher.UIThread.Invoke(() => ViewContent = new FileHistoriesRevisionFile(_file, module));
}
});
break;
default:
ViewContent = new FileHistoriesRevisionFile(_file, null);
break;
}
}
private void SetViewContentAsDiff()
{
var option = new Models.DiffOption(_selectedCommit, _file);
ViewContent = new DiffContext(_repo.FullPath, option, _viewContent as DiffContext);
}
[GeneratedRegex(@"^version https://git-lfs.github.com/spec/v\d+\r?\noid sha256:([0-9a-f]+)\r?\nsize (\d+)[\r\n]*$")]
private static partial Regex REG_LFS_FORMAT();
private static readonly HashSet<string> IMG_EXTS = new HashSet<string>()
{
".ico", ".bmp", ".jpg", ".png", ".jpeg"
};
private readonly Repository _repo = null;
private readonly string _file = null;
private bool _isLoading = true;
private List<Models.Commit> _commits = null;
private Models.Commit _selectedCommit = null;
private DiffContext _diffContext = null;
private CommitDetail _detailContext = null;
private int _viewMode = 0;
private object _viewContent = null;
}
}

View file

@ -1,9 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Avalonia.VisualTree;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
@ -240,6 +242,25 @@ namespace SourceGit.ViewModels
e.Handled = true;
};
menu.Items.Add(reset);
var squash = new MenuItem();
squash.Header = App.Text("CommitCM.SquashCommitsSinceThis");
squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent");
squash.IsVisible = commit.IsMerged;
squash.Click += (_, e) =>
{
if (_repo.LocalChangesCount > 0)
{
App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first.");
return;
}
if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Squash(_repo, commit, commit.SHA));
e.Handled = true;
};
menu.Items.Add(squash);
}
else
{
@ -276,7 +297,7 @@ namespace SourceGit.ViewModels
{
var parent = _commits.Find(x => x.SHA == commit.Parents[0]);
if (parent != null && PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Squash(_repo, commit, parent));
PopupHost.ShowPopup(new Squash(_repo, parent, commit.SHA));
}
e.Handled = true;
@ -428,12 +449,12 @@ namespace SourceGit.ViewModels
saveToPatch.Header = App.Text("CommitCM.SaveAsPatch");
saveToPatch.Click += async (_, e) =>
{
var topLevel = App.GetTopLevel();
if (topLevel == null)
var storageProvider = App.GetStorageProvider();
if (storageProvider == null)
return;
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
var selected = await storageProvider.OpenFolderPickerAsync(options);
if (selected.Count == 1)
{
var succ = new Commands.FormatPatch(_repo.FullPath, commit.SHA, selected[0].Path.LocalPath).Exec();

View file

@ -32,6 +32,7 @@ namespace SourceGit.ViewModels
{
var normalizedPath = _targetPath.Replace("\\", "/");
Preference.Instance.FindOrAddNodeByRepositoryPath(normalizedPath, _parentNode, true);
Welcome.Instance.Refresh();
});
return true;

View file

@ -48,6 +48,7 @@ namespace SourceGit.ViewModels
var normalized = root.Replace("\\", "/");
var node = pref.FindOrAddNodeByRepositoryPath(normalized, null, false);
Welcome.Instance.Refresh();
OpenRepositoryInTab(node, null);
}
else if (pref.RestoreTabs)
@ -144,6 +145,7 @@ namespace SourceGit.ViewModels
Models.AutoFetchManager.Instance.RemoveRepository(repo.FullPath);
repo.Close();
Welcome.Instance.ClearSearchFilter();
last.Node = new RepositoryNode() { Id = Guid.NewGuid().ToString() };
last.Data = Welcome.Instance;
last.Popup = null;

View file

@ -28,6 +28,9 @@ namespace SourceGit.ViewModels
{
_node = new RepositoryNode() { Id = Guid.NewGuid().ToString() };
_data = Welcome.Instance;
// New welcome page will clear the search filter before.
Welcome.Instance.ClearSearchFilter();
}
public LauncherPage(RepositoryNode node, Repository repo)

View file

@ -4,9 +4,6 @@ using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using Avalonia.Collections;
using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
@ -20,6 +17,7 @@ namespace SourceGit.ViewModels
{
if (_instance == null)
{
_isLoading = true;
if (!File.Exists(_savePath))
{
_instance = new Preference();
@ -35,14 +33,9 @@ namespace SourceGit.ViewModels
_instance = new Preference();
}
}
_isLoading = false;
}
if (_instance.DefaultFont == null)
_instance.DefaultFont = FontManager.Current.DefaultFontFamily;
if (_instance.MonospaceFont == null)
_instance.MonospaceFont = new FontFamily("fonts:SourceGit#JetBrains Mono");
if (!_instance.IsGitConfigured())
_instance.GitInstallPath = Native.OS.FindGitExecutable();
@ -55,7 +48,7 @@ namespace SourceGit.ViewModels
get => _locale;
set
{
if (SetProperty(ref _locale, value))
if (SetProperty(ref _locale, value) && !_isLoading)
App.SetLocale(value);
}
}
@ -65,7 +58,7 @@ namespace SourceGit.ViewModels
get => _theme;
set
{
if (SetProperty(ref _theme, value))
if (SetProperty(ref _theme, value) && !_isLoading)
App.SetTheme(_theme, _themeOverrides);
}
}
@ -75,47 +68,47 @@ namespace SourceGit.ViewModels
get => _themeOverrides;
set
{
if (SetProperty(ref _themeOverrides, value))
if (SetProperty(ref _themeOverrides, value) && !_isLoading)
App.SetTheme(_theme, value);
}
}
public FontFamily DefaultFont
public string DefaultFontFamily
{
get => _defaultFont;
get => _defaultFontFamily;
set
{
if (SetProperty(ref _defaultFont, value) && _onlyUseMonoFontInEditor)
OnPropertyChanged(nameof(PrimaryFont));
if (SetProperty(ref _defaultFontFamily, value) && !_isLoading)
App.SetFonts(_defaultFontFamily, _monospaceFontFamily, _onlyUseMonoFontInEditor);
}
}
public FontFamily MonospaceFont
public string MonospaceFontFamily
{
get => _monospaceFont;
get => _monospaceFontFamily;
set
{
if (SetProperty(ref _monospaceFont, value) && !_onlyUseMonoFontInEditor)
OnPropertyChanged(nameof(PrimaryFont));
if (SetProperty(ref _monospaceFontFamily, value) && !_isLoading)
App.SetFonts(_defaultFontFamily, _monospaceFontFamily, _onlyUseMonoFontInEditor);
}
}
[JsonIgnore]
public FontFamily PrimaryFont
{
get => _onlyUseMonoFontInEditor ? _defaultFont : _monospaceFont;
}
public bool OnlyUseMonoFontInEditor
{
get => _onlyUseMonoFontInEditor;
set
{
if (SetProperty(ref _onlyUseMonoFontInEditor, value))
OnPropertyChanged(nameof(PrimaryFont));
if (SetProperty(ref _onlyUseMonoFontInEditor, value) && !_isLoading)
App.SetFonts(_defaultFontFamily, _monospaceFontFamily, _onlyUseMonoFontInEditor);
}
}
public bool UseSystemWindowFrame
{
get => _useSystemWindowFrame;
set => SetProperty(ref _useSystemWindowFrame, value);
}
public double DefaultFontSize
{
get => _defaultFontSize;
@ -206,12 +199,6 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _showHiddenSymbolsInDiffView, value);
}
public int DiffViewVisualLineNumbers
{
get => _diffViewVisualLineNumbers;
set => SetProperty(ref _diffViewVisualLineNumbers, value);
}
public Models.ChangeViewMode UnstagedChangeViewMode
{
get => _unstagedChangeViewMode;
@ -311,11 +298,11 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _externalMergeToolPath, value);
}
public AvaloniaList<RepositoryNode> RepositoryNodes
public List<RepositoryNode> RepositoryNodes
{
get => _repositoryNodes;
set => SetProperty(ref _repositoryNodes, value);
}
get;
set;
} = [];
public List<string> OpenedTabs
{
@ -358,21 +345,15 @@ namespace SourceGit.ViewModels
public void AddNode(RepositoryNode node, RepositoryNode to = null)
{
var collection = to == null ? _repositoryNodes : to.SubNodes;
var list = new List<RepositoryNode>();
list.AddRange(collection);
list.Add(node);
list.Sort((l, r) =>
var collection = to == null ? RepositoryNodes : to.SubNodes;
collection.Add(node);
collection.Sort((l, r) =>
{
if (l.IsRepository != r.IsRepository)
return l.IsRepository ? 1 : -1;
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
});
collection.Clear();
foreach (var one in list)
collection.Add(one);
}
public RepositoryNode FindNode(string id)
@ -405,7 +386,7 @@ namespace SourceGit.ViewModels
public void MoveNode(RepositoryNode node, RepositoryNode to = null)
{
if (to == null && _repositoryNodes.Contains(node))
if (to == null && RepositoryNodes.Contains(node))
return;
if (to != null && to.SubNodes.Contains(node))
return;
@ -416,28 +397,19 @@ namespace SourceGit.ViewModels
public void RemoveNode(RepositoryNode node)
{
RemoveNodeRecursive(node, _repositoryNodes);
RemoveNodeRecursive(node, RepositoryNodes);
}
public void SortByRenamedNode(RepositoryNode node)
{
var container = FindNodeContainer(node, _repositoryNodes);
if (container == null)
return;
var list = new List<RepositoryNode>();
list.AddRange(container);
list.Sort((l, r) =>
var container = FindNodeContainer(node, RepositoryNodes);
container?.Sort((l, r) =>
{
if (l.IsRepository != r.IsRepository)
return l.IsRepository ? 1 : -1;
return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
});
container.Clear();
foreach (var one in list)
container.Add(one);
}
public void Save()
@ -446,7 +418,7 @@ namespace SourceGit.ViewModels
File.WriteAllText(_savePath, data);
}
private RepositoryNode FindNodeRecursive(string id, AvaloniaList<RepositoryNode> collection)
private RepositoryNode FindNodeRecursive(string id, List<RepositoryNode> collection)
{
foreach (var node in collection)
{
@ -461,7 +433,7 @@ namespace SourceGit.ViewModels
return null;
}
private AvaloniaList<RepositoryNode> FindNodeContainer(RepositoryNode node, AvaloniaList<RepositoryNode> collection)
private List<RepositoryNode> FindNodeContainer(RepositoryNode node, List<RepositoryNode> collection)
{
foreach (var sub in collection)
{
@ -476,7 +448,7 @@ namespace SourceGit.ViewModels
return null;
}
private bool RemoveNodeRecursive(RepositoryNode node, AvaloniaList<RepositoryNode> collection)
private bool RemoveNodeRecursive(RepositoryNode node, List<RepositoryNode> collection)
{
if (collection.Contains(node))
{
@ -494,14 +466,16 @@ namespace SourceGit.ViewModels
}
private static Preference _instance = null;
private static bool _isLoading = false;
private static readonly string _savePath = Path.Combine(Native.OS.DataDir, "preference.json");
private string _locale = "en_US";
private string _theme = "Default";
private string _themeOverrides = string.Empty;
private FontFamily _defaultFont = null;
private FontFamily _monospaceFont = null;
private string _defaultFontFamily = string.Empty;
private string _monospaceFontFamily = string.Empty;
private bool _onlyUseMonoFontInEditor = false;
private bool _useSystemWindowFrame = false;
private double _defaultFontSize = 13;
private LayoutInfo _layout = new LayoutInfo();
@ -518,7 +492,6 @@ namespace SourceGit.ViewModels
private bool _useSyntaxHighlighting = false;
private bool _enableDiffViewWordWrap = false;
private bool _showHiddenSymbolsInDiffView = false;
private int _diffViewVisualLineNumbers = 4;
private Models.ChangeViewMode _unstagedChangeViewMode = Models.ChangeViewMode.List;
private Models.ChangeViewMode _stagedChangeViewMode = Models.ChangeViewMode.List;
@ -528,7 +501,5 @@ namespace SourceGit.ViewModels
private int _externalMergeToolType = 0;
private string _externalMergeToolPath = string.Empty;
private AvaloniaList<RepositoryNode> _repositoryNodes = new AvaloniaList<RepositoryNode>();
}
}

View file

@ -62,12 +62,6 @@ namespace SourceGit.ViewModels
}
}
public bool PushAllTags
{
get => _repo.Settings.PushAllTags;
set => _repo.Settings.PushAllTags = value;
}
public bool IsSetTrackOptionVisible
{
get => _isSetTrackOptionVisible;
@ -80,6 +74,23 @@ namespace SourceGit.ViewModels
set;
} = true;
public bool IsCheckSubmodulesVisible
{
get => _repo.Submodules.Count > 0;
}
public bool CheckSubmodules
{
get;
set;
} = true;
public bool PushAllTags
{
get => _repo.Settings.PushAllTags;
set => _repo.Settings.PushAllTags = value;
}
public bool ForcePush
{
get;
@ -151,8 +162,9 @@ namespace SourceGit.ViewModels
_selectedRemote.Name,
remoteBranchName,
PushAllTags,
ForcePush,
_repo.Submodules.Count > 0 && CheckSubmodules,
_isSetTrackOptionVisible && Tracking,
ForcePush,
SetProgressDescription).Exec();
CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ;

View file

@ -73,6 +73,16 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _selectedView, value);
}
public bool EnableFirstParentInHistories
{
get => _enableFirstParentInHistories;
set
{
if (SetProperty(ref _enableFirstParentInHistories, value))
Task.Run(RefreshCommits);
}
}
public string SearchBranchFilter
{
get => _searchBranchFilter;
@ -724,6 +734,9 @@ namespace SourceGit.ViewModels
Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true);
var limits = $"-{Preference.Instance.MaxHistoryCommits} ";
if (_enableFirstParentInHistories)
limits += "--first-parent ";
var validFilters = new List<string>();
foreach (var filter in _settings.Filters)
{
@ -758,7 +771,7 @@ namespace SourceGit.ViewModels
}
var commits = new Commands.QueryCommits(_fullpath, limits).Result();
var graph = Models.CommitGraph.Parse(commits);
var graph = Models.CommitGraph.Parse(commits, _enableFirstParentInHistories);
Dispatcher.UIThread.Invoke(() =>
{
@ -940,9 +953,7 @@ namespace SourceGit.ViewModels
};
}
var launcher = App.GetTopLevel().DataContext as Launcher;
if (launcher != null)
launcher.OpenRepositoryInTab(node, null);
App.GetLauncer()?.OpenRepositoryInTab(node, null);
}
public void AddWorktree()
@ -971,9 +982,7 @@ namespace SourceGit.ViewModels
};
}
var launcher = App.GetTopLevel().DataContext as Launcher;
if (launcher != null)
launcher.OpenRepositoryInTab(node, null);
App.GetLauncer()?.OpenRepositoryInTab(node, null);
}
public ContextMenu CreateContextMenuForGitFlow()
@ -1130,12 +1139,8 @@ namespace SourceGit.ViewModels
{
locks.Click += (_, e) =>
{
var topLevel = App.GetTopLevel() as Window;
if (topLevel == null)
return;
var dialog = new Views.LFSLocks() { DataContext = new LFSLocks(_fullpath, _remotes[0].Name) };
dialog.Show(topLevel);
App.OpenDialog(dialog);
e.Handled = true;
};
}
@ -1148,12 +1153,8 @@ namespace SourceGit.ViewModels
lockRemote.Header = remoteName;
lockRemote.Click += (_, e) =>
{
var topLevel = App.GetTopLevel() as Window;
if (topLevel == null)
return;
var dialog = new Views.LFSLocks() { DataContext = new LFSLocks(_fullpath, remoteName) };
dialog.Show(topLevel);
App.OpenDialog(dialog);
e.Handled = true;
};
locks.Items.Add(lockRemote);
@ -1878,16 +1879,10 @@ namespace SourceGit.ViewModels
target.Icon = App.CreateMenuIcon(b.IsCurrent ? "Icons.Check" : "Icons.Branch");
target.Click += (_, e) =>
{
var topLevel = App.GetTopLevel() as Window;
if (topLevel == null)
return;
var wnd = new Views.BranchCompare()
App.OpenDialog(new Views.BranchCompare()
{
DataContext = new BranchCompare(_fullpath, branch, dup)
};
wnd.Show(topLevel);
});
e.Handled = true;
};
@ -1975,6 +1970,7 @@ namespace SourceGit.ViewModels
private bool _isSearchLoadingVisible = false;
private bool _isSearchCommitSuggestionOpen = false;
private int _searchCommitFilterType = 0;
private bool _enableFirstParentInHistories = false;
private string _searchCommitFilter = string.Empty;
private List<Models.Commit> _searchedCommits = new List<Models.Commit>();
private List<string> _revisionFiles = new List<string>();

View file

@ -1,6 +1,5 @@
using System.Text.Json.Serialization;
using Avalonia.Collections;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using CommunityToolkit.Mvvm.ComponentModel;
@ -49,11 +48,18 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _isVisible, value);
}
public AvaloniaList<RepositoryNode> SubNodes
[JsonIgnore]
public int Depth
{
get => _subNodes;
set => SetProperty(ref _subNodes, value);
}
get;
set;
} = 0;
public List<RepositoryNode> SubNodes
{
get;
set;
} = [];
public void Edit()
{
@ -93,6 +99,5 @@ namespace SourceGit.ViewModels
private int _bookmark = 0;
private bool _isExpanded = false;
private bool _isVisible = true;
private AvaloniaList<RepositoryNode> _subNodes = new AvaloniaList<RepositoryNode>();
}
}

View file

@ -5,16 +5,9 @@ namespace SourceGit.ViewModels
{
public class Squash : Popup
{
public Models.Commit Head
public Models.Commit Target
{
get;
private set;
}
public Models.Commit Parent
{
get;
private set;
get => _target;
}
[Required(ErrorMessage = "Commit message is required!!!")]
@ -24,13 +17,12 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _message, value, true);
}
public Squash(Repository repo, Models.Commit head, Models.Commit parent)
public Squash(Repository repo, Models.Commit target, string shaToGetPreferMessage)
{
_repo = repo;
_message = new Commands.QueryCommitFullMessage(_repo.FullPath, head.SHA).Result();
_target = target;
_message = new Commands.QueryCommitFullMessage(_repo.FullPath, shaToGetPreferMessage).Result();
Head = head;
Parent = parent;
View = new Views.Squash() { DataContext = this };
}
@ -41,7 +33,7 @@ namespace SourceGit.ViewModels
return Task.Run(() =>
{
var succ = new Commands.Reset(_repo.FullPath, Parent.SHA, "--soft").Exec();
var succ = new Commands.Reset(_repo.FullPath, Target.SHA, "--soft").Exec();
if (succ)
succ = new Commands.Commit(_repo.FullPath, _message, true).Exec();
CallUIThread(() => _repo.SetWatcherEnabled(true));
@ -50,6 +42,7 @@ namespace SourceGit.ViewModels
}
private readonly Repository _repo;
private Models.Commit _target;
private string _message;
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Avalonia.Collections;
using Avalonia.Controls;
@ -11,10 +12,11 @@ namespace SourceGit.ViewModels
{
public static Welcome Instance => _instance;
public AvaloniaList<RepositoryNode> RepositoryNodes
public AvaloniaList<RepositoryNode> Rows
{
get => Preference.Instance.RepositoryNodes;
}
get;
private set;
} = [];
public string SearchFilter
{
@ -26,6 +28,60 @@ namespace SourceGit.ViewModels
}
}
public Welcome()
{
Refresh();
}
public void Refresh()
{
if (string.IsNullOrWhiteSpace(_searchFilter))
{
foreach (var node in Preference.Instance.RepositoryNodes)
ResetVisibility(node);
}
else
{
foreach (var node in Preference.Instance.RepositoryNodes)
SetVisibilityBySearch(node);
}
var rows = new List<RepositoryNode>();
MakeTreeRows(rows, Preference.Instance.RepositoryNodes);
Rows.Clear();
Rows.AddRange(rows);
}
public void ToggleNodeIsExpanded(RepositoryNode node)
{
node.IsExpanded = !node.IsExpanded;
var depth = node.Depth;
var idx = Rows.IndexOf(node);
if (idx == -1)
return;
if (node.IsExpanded)
{
var subrows = new List<RepositoryNode>();
MakeTreeRows(subrows, node.SubNodes, depth + 1);
Rows.InsertRange(idx + 1, subrows);
}
else
{
var removeCount = 0;
for (int i = idx + 1; i < Rows.Count; i++)
{
var row = Rows[i];
if (row.Depth <= depth)
break;
removeCount++;
}
Rows.RemoveRange(idx + 1, removeCount);
}
}
public void InitRepository(string path, RepositoryNode parent)
{
if (!Preference.Instance.IsGitConfigured())
@ -35,10 +91,8 @@ namespace SourceGit.ViewModels
}
if (PopupHost.CanCreatePopup())
{
PopupHost.ShowPopup(new Init(path, parent));
}
}
public void Clone()
{
@ -74,6 +128,7 @@ namespace SourceGit.ViewModels
public void MoveNode(RepositoryNode from, RepositoryNode to)
{
Preference.Instance.MoveNode(from, to);
Refresh();
}
public ContextMenu CreateContextMenu(RepositoryNode node)
@ -153,20 +208,6 @@ namespace SourceGit.ViewModels
return menu;
}
private void Refresh()
{
if (string.IsNullOrWhiteSpace(_searchFilter))
{
foreach (var node in RepositoryNodes)
ResetVisibility(node);
}
else
{
foreach (var node in RepositoryNodes)
SetVisibilityBySearch(node);
}
}
private void ResetVisibility(RepositoryNode node)
{
node.IsVisible = true;
@ -197,7 +238,25 @@ namespace SourceGit.ViewModels
}
else
{
node.IsVisible = node.Name.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase);
node.IsVisible = node.Name.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase) ||
node.Id.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase);
}
}
private void MakeTreeRows(List<RepositoryNode> rows, List<RepositoryNode> nodes, int depth = 0)
{
foreach (var node in nodes)
{
if (!node.IsVisible)
continue;
node.Depth = depth;
rows.Add(node);
if (node.IsRepository || !node.IsExpanded)
continue;
MakeTreeRows(rows, node.SubNodes, depth + 1);
}
}

View file

@ -303,16 +303,10 @@ namespace SourceGit.ViewModels
public void OpenAssumeUnchanged()
{
var toplevel = App.GetTopLevel() as Window;
if (toplevel == null)
return;
var dialog = new Views.AssumeUnchangedManager()
App.OpenDialog(new Views.AssumeUnchangedManager()
{
DataContext = new AssumeUnchangedManager(_repo.FullPath)
};
dialog.ShowDialog(toplevel);
});
}
public void StashAll(bool autoStart)
@ -530,8 +524,8 @@ namespace SourceGit.ViewModels
patch.Icon = App.CreateMenuIcon("Icons.Diff");
patch.Click += async (_, e) =>
{
var topLevel = App.GetTopLevel();
if (topLevel == null)
var storageProvider = App.GetStorageProvider();
if (storageProvider == null)
return;
var options = new FilePickerSaveOptions();
@ -539,7 +533,7 @@ namespace SourceGit.ViewModels
options.DefaultExtension = ".patch";
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedUnstaged, true, storageFile.Path.LocalPath));
@ -853,8 +847,8 @@ namespace SourceGit.ViewModels
patch.Icon = App.CreateMenuIcon("Icons.Diff");
patch.Click += async (_, e) =>
{
var topLevel = App.GetTopLevel();
if (topLevel == null)
var storageProvider = App.GetStorageProvider();
if (storageProvider == null)
return;
var options = new FilePickerSaveOptions();
@ -862,7 +856,7 @@ namespace SourceGit.ViewModels
options.DefaultExtension = ".patch";
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedUnstaged, true, storageFile.Path.LocalPath));
@ -938,8 +932,8 @@ namespace SourceGit.ViewModels
patch.Icon = App.CreateMenuIcon("Icons.Diff");
patch.Click += async (_, e) =>
{
var topLevel = App.GetTopLevel();
if (topLevel == null)
var storageProvider = App.GetStorageProvider();
if (storageProvider == null)
return;
var options = new FilePickerSaveOptions();
@ -947,7 +941,7 @@ namespace SourceGit.ViewModels
options.DefaultExtension = ".patch";
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedStaged, false, storageFile.Path.LocalPath));
@ -1085,9 +1079,8 @@ namespace SourceGit.ViewModels
stash.Click += (_, e) =>
{
if (PopupHost.CanCreatePopup())
{
PopupHost.ShowPopup(new StashChanges(_repo, _selectedStaged, false));
}
e.Handled = true;
};
@ -1096,8 +1089,8 @@ namespace SourceGit.ViewModels
patch.Icon = App.CreateMenuIcon("Icons.Diff");
patch.Click += async (_, e) =>
{
var topLevel = App.GetTopLevel();
if (topLevel == null)
var storageProvider = App.GetStorageProvider();
if (storageProvider == null)
return;
var options = new FilePickerSaveOptions();
@ -1105,7 +1098,7 @@ namespace SourceGit.ViewModels
options.DefaultExtension = ".patch";
options.FileTypeChoices = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }];
var storageFile = await topLevel.StorageProvider.SaveFilePickerAsync(options);
var storageFile = await storageProvider.SaveFilePickerAsync(options);
if (storageFile != null)
{
var succ = await Task.Run(() => Commands.SaveChangesAsPatch.Exec(_repo.FullPath, _selectedStaged, false, storageFile.Path.LocalPath));

View file

@ -13,7 +13,7 @@
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -13,7 +13,7 @@
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -8,6 +8,7 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.AssumeUnchangedManager"
x:DataType="vm:AssumeUnchangedManager"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.AssumeUnchanged}"
Width="600" Height="400"
@ -15,7 +16,7 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -105,7 +105,8 @@ namespace SourceGit.Views
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
};
var typeface = new Typeface("fonts:SourceGit#JetBrains Mono");
var fontFamily = avatar.FindResource("Fonts.Monospace") as FontFamily;
var typeface = new Typeface(fontFamily);
avatar._fallbackLabel = new FormattedText(
placeholder,

View file

@ -7,18 +7,19 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.Blame"
x:DataType="vm:Blame"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.Blame}"
MinWidth="1280" MinHeight="720">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="24"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="4"
Background="{DynamicResource Brush.TitleBar}"
@ -58,7 +59,7 @@
BorderThickness="1"
Background="{DynamicResource Brush.Contents}"
Foreground="{DynamicResource Brush.FG1}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontFamily="{DynamicResource Fonts.Monospace}"
BlameData="{Binding Data}"/>
<!-- Not supported mask (for binary files) -->

View file

@ -8,19 +8,20 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.BranchCompare"
x:DataType="vm:BranchCompare"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.BranchCompare}"
MinWidth="1280" MinHeight="720"
WindowStartupLocation="CenterOwner">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="64"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="4"
Background="{DynamicResource Brush.TitleBar}"

View file

@ -8,50 +8,26 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.BranchTree"
x:Name="ThisControl">
<DataGrid x:Name="BranchesPresenter"
<ListBox x:Name="BranchesPresenter"
Classes="repo_left_content_list"
ItemsSource="{Binding #ThisControl.Rows}"
Background="Transparent"
RowHeight="24"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
HeadersVisibility="None"
SelectionMode="Multiple"
SelectionChanged="OnNodesSelectionChanged"
ContextRequested="OnTreeContextRequested">
<DataGrid.Styles>
<Style Selector="DataGridRow" x:DataType="vm:BranchTreeNode">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>
<Style Selector="ListBoxItem" x:DataType="vm:BranchTreeNode">
<Setter Property="CornerRadius" Value="{Binding CornerRadius}"/>
<Setter Property="Height" Value="24"/>
</Style>
</ListBox.Styles>
<Style Selector="DataGridRow /template/ Border#RowBorder">
<Setter Property="ClipToBounds" Value="True" />
</Style>
<Style Selector="Grid.repository_leftpanel DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
<Setter Property="Opacity" Value=".5"/>
</Style>
<Style Selector="Grid.repository_leftpanel DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
<Setter Property="Opacity" Value="1"/>
</Style>
<Style Selector="Grid.repository_leftpanel:focus-within DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".65"/>
</Style>
<Style Selector="Grid.repository_leftpanel:focus-within DataGridRow:selected:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".8"/>
</Style>
</DataGrid.Styles>
<DataGrid.Columns>
<DataGridTemplateColumn Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="vm:BranchTreeNode">
<ListBox.ItemTemplate>
<DataTemplate DataType="vm:BranchTreeNode">
<Grid Height="24"
Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}"
ColumnDefinitions="16,*"
@ -86,7 +62,7 @@
<v:BranchTreeNodeTrackStatusPresenter Grid.Column="2"
Margin="8,0"
VerticalAlignment="Center"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="10"
Foreground="{DynamicResource Brush.BadgeFG}"
Background="{DynamicResource Brush.Badge}"/>
@ -103,9 +79,7 @@
</Grid>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>

View file

@ -13,7 +13,12 @@
Classes="bold"
Text="{DynamicResource Text.Checkout}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="140,*">
<Grid Margin="0,16,0,0" ColumnDefinitions="140,*">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="Auto" MinHeight="32"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -27,23 +32,23 @@
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.Checkout.LocalChanges}"/>
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
<StackPanel.Resources>
<WrapPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<WrapPanel.Resources>
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
</StackPanel.Resources>
</WrapPanel.Resources>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}"
GroupName="LocalChanges"
Margin="0,0,8,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}"
GroupName="LocalChanges"
Margin="8,0,0,0"
Margin="0,0,8,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}"
GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/>
</StackPanel>
</WrapPanel>
</Grid>
</StackPanel>
</UserControl>

View file

@ -3,20 +3,44 @@
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Platform;
namespace SourceGit.Views
{
public class ChromelessWindow : Window
{
public bool UseSystemWindowFrame
{
get => OperatingSystem.IsLinux() && ViewModels.Preference.Instance.UseSystemWindowFrame;
}
protected override Type StyleKeyOverride => typeof(Window);
public ChromelessWindow()
{
if (OperatingSystem.IsLinux())
{
if (UseSystemWindowFrame)
{
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.Default;
ExtendClientAreaToDecorationsHint = false;
}
else
{
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome;
ExtendClientAreaToDecorationsHint = true;
Classes.Add("custom_window_frame");
else if (OperatingSystem.IsWindows())
}
}
else
{
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome;
ExtendClientAreaToDecorationsHint = true;
if (OperatingSystem.IsWindows())
Classes.Add("fix_maximized_padding");
}
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{

View file

@ -57,12 +57,16 @@
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
<SelectableTextBlock Classes="primary"
Text="{Binding SHA}"
Margin="12,0,0,0"
Margin="12,0,4,0"
VerticalAlignment="Center"/>
<Button Classes="icon_button" Cursor="Hand" Click="OnOpenWebLink" IsVisible="{Binding #ThisControl.WebLinks, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}">
<Button Classes="icon_button" Width="24" Cursor="Hand" Click="OnOpenWebLink" IsVisible="{Binding #ThisControl.WebLinks, Converter={x:Static c:ListConverters.IsNotNullOrEmpty}}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Link}" Fill="{DynamicResource Brush.Link}"/>
</Button>
<Button Classes="icon_button" Width="24" Cursor="Hand" Click="OnOpenContainsIn" IsVisible="{Binding #ThisControl.SupportsContainsIn}" ToolTip.Tip="{DynamicResource Text.CommitDetail.Info.ContainsIn}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Relation}"/>
</Button>
</StackPanel>
@ -94,11 +98,13 @@
<v:CommitRefsPresenter IconBackground="{DynamicResource Brush.DecoratorIconBG}"
IconForeground="{DynamicResource Brush.DecoratorIcon}"
BranchNameBackground="{DynamicResource Brush.DecoratorBranch}"
HeadBranchNameBackground="{DynamicResource Brush.DecoratorHead}"
TagNameBackground="{DynamicResource Brush.DecoratorTag}"
LabelForeground="{DynamicResource Brush.DecoratorFG}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontSize="10"
VerticalAlignment="Center"/>
FontFamily="{DynamicResource Fonts.Primary}"
FontSize="11"
VerticalAlignment="Center"
Refs="{Binding Decorators}"/>
</Border>
<!-- Messages -->

View file

@ -17,6 +17,15 @@ namespace SourceGit.Views
set => SetValue(MessageProperty, value);
}
public static readonly StyledProperty<bool> SupportsContainsInProperty =
AvaloniaProperty.Register<CommitBaseInfo, bool>(nameof(SupportsContainsIn));
public bool SupportsContainsIn
{
get => GetValue(SupportsContainsInProperty);
set => SetValue(SupportsContainsInProperty, value);
}
public static readonly StyledProperty<AvaloniaList<Models.CommitLink>> WebLinksProperty =
AvaloniaProperty.Register<CommitBaseInfo, AvaloniaList<Models.CommitLink>>(nameof(WebLinks));
@ -74,6 +83,19 @@ namespace SourceGit.Views
e.Handled = true;
}
private void OnOpenContainsIn(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.CommitDetail detail && sender is Button button)
{
var tracking = new CommitRelationTracking(detail);
var flyout = new Flyout();
flyout.Content = tracking;
flyout.ShowAt(button);
}
e.Handled = true;
}
private void OnParentSHAPressed(object sender, PointerPressedEventArgs e)
{
if (DataContext is ViewModels.CommitDetail detail && sender is Control { DataContext: string sha })

View file

@ -21,6 +21,7 @@
<!-- Base Information -->
<v:CommitBaseInfo Content="{Binding Commit}"
Message="{Binding FullMessage}"
SupportsContainsIn="True"
WebLinks="{Binding WebLinks}"
IssueTrackerRules="{Binding IssueTrackerRules}"/>

View file

@ -1,17 +1,21 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Input;
using Avalonia.Utilities;
using Avalonia.VisualTree;
namespace SourceGit.Views
{
public class CommitMessagePresenter : SelectableTextBlock
public partial class CommitMessagePresenter : SelectableTextBlock
{
[GeneratedRegex(@"\b([0-9a-fA-F]{8,40})\b")]
private static partial Regex REG_SHA_FORMAT();
public static readonly StyledProperty<string> MessageProperty =
AvaloniaProperty.Register<CommitMessagePresenter, string>(nameof(Message));
@ -38,7 +42,7 @@ namespace SourceGit.Views
if (change.Property == MessageProperty || change.Property == IssueTrackerRulesProperty)
{
Inlines.Clear();
Inlines!.Clear();
_matches = null;
ClearHoveredIssueLink();
@ -46,16 +50,35 @@ namespace SourceGit.Views
if (string.IsNullOrEmpty(message))
return;
var rules = IssueTrackerRules;
if (rules == null || rules.Count == 0)
var matches = new List<Models.Hyperlink>();
if (IssueTrackerRules is { Count: > 0 } rules)
{
Inlines.Add(new Run(message));
return;
}
var matches = new List<Models.IssueTrackerMatch>();
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)
{
@ -72,9 +95,9 @@ namespace SourceGit.Views
if (match.Start > pos)
Inlines.Add(new Run(message.Substring(pos, match.Start - pos)));
match.Link = new Run(message.Substring(match.Start, match.Length));
match.Link.Classes.Add("issue_link");
Inlines.Add(match.Link);
var link = new Run(message.Substring(match.Start, match.Length));
link.Classes.Add(match.IsCommitSHA ? "commit_link" : "issue_link");
Inlines.Add(link);
pos = match.Start + match.Length;
}
@ -90,11 +113,10 @@ namespace SourceGit.Views
if (e.Pointer.Captured == null && _matches != null)
{
var padding = Padding;
var point = e.GetPosition(this) - new Point(padding.Left, padding.Top);
point = new Point(
MathUtilities.Clamp(point.X, 0, Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)),
MathUtilities.Clamp(point.Y, 0, Math.Max(TextLayout.Height, 0)));
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));
var y = Math.Min(Math.Max(point.Y, 0), Math.Max(TextLayout.Height, 0));
point = new Point(x, y);
var pos = TextLayout.HitTestPoint(point).TextPosition;
foreach (var match in _matches)
@ -105,12 +127,15 @@ namespace SourceGit.Views
if (match == _lastHover)
return;
_lastHover = match;
//_lastHover.Link.Classes.Add("issue_link_hovered");
SetCurrentValue(CursorProperty, Cursor.Parse("Hand"));
ToolTip.SetTip(this, match.URL);
_lastHover = match;
if (!_lastHover.IsCommitSHA)
{
ToolTip.SetTip(this, match.Link);
ToolTip.SetIsOpen(this, true);
}
return;
}
@ -123,7 +148,18 @@ namespace SourceGit.Views
if (_lastHover != null)
{
e.Pointer.Capture(null);
Native.OS.OpenBrowser(_lastHover.URL);
if (_lastHover.IsCommitSHA)
{
var parentView = this.FindAncestorOfType<CommitBaseInfo>();
if (parentView is { DataContext: ViewModels.CommitDetail detail })
detail.NavigateTo(_lastHover.Link);
}
else
{
Native.OS.OpenBrowser(_lastHover.Link);
}
e.Handled = true;
return;
}
@ -143,12 +179,11 @@ namespace SourceGit.Views
{
ToolTip.SetTip(this, null);
SetCurrentValue(CursorProperty, Cursor.Parse("IBeam"));
//_lastHover.Link.Classes.Remove("issue_link_hovered");
_lastHover = null;
}
}
private List<Models.IssueTrackerMatch> _matches = null;
private Models.IssueTrackerMatch _lastHover = null;
private List<Models.Hyperlink> _matches = null;
private Models.Hyperlink _lastHover = null;
}
}

View file

@ -14,7 +14,16 @@ namespace SourceGit.Views
{
public Geometry Icon { get; set; } = null;
public FormattedText Label { get; set; } = null;
public bool IsTag { get; set; } = false;
public IBrush LabelBG { get; set; } = null;
}
public static readonly StyledProperty<List<Models.Decorator>> RefsProperty =
AvaloniaProperty.Register<CommitRefsPresenter, List<Models.Decorator>>(nameof(Refs));
public List<Models.Decorator> Refs
{
get => GetValue(RefsProperty);
set => SetValue(RefsProperty, value);
}
public static readonly StyledProperty<FontFamily> FontFamilyProperty =
@ -71,6 +80,15 @@ namespace SourceGit.Views
set => SetValue(BranchNameBackgroundProperty, value);
}
public static readonly StyledProperty<IBrush> HeadBranchNameBackgroundProperty =
AvaloniaProperty.Register<CommitRefsPresenter, IBrush>(nameof(HeadBranchNameBackground), Brushes.White);
public IBrush HeadBranchNameBackground
{
get => GetValue(HeadBranchNameBackgroundProperty);
set => SetValue(HeadBranchNameBackgroundProperty, value);
}
public static readonly StyledProperty<IBrush> TagNameBackgroundProperty =
AvaloniaProperty.Register<CommitRefsPresenter, IBrush>(nameof(TagNameBackground), Brushes.White);
@ -85,7 +103,8 @@ namespace SourceGit.Views
AffectsMeasure<CommitRefsPresenter>(
FontFamilyProperty,
FontSizeProperty,
LabelForegroundProperty);
LabelForegroundProperty,
RefsProperty);
AffectsRender<CommitRefsPresenter>(
IconBackgroundProperty,
@ -101,8 +120,6 @@ namespace SourceGit.Views
var iconFG = IconForeground;
var iconBG = IconBackground;
var branchBG = BranchNameBackground;
var tagBG = TagNameBackground;
var x = 0.0;
foreach (var item in _items)
@ -111,7 +128,7 @@ namespace SourceGit.Views
var labelRect = new RoundedRect(new Rect(x + 16, 0, item.Label.Width + 8, 16), new CornerRadius(0, 2, 2, 0));
context.DrawRectangle(iconBG, null, iconRect);
context.DrawRectangle(item.IsTag ? tagBG : branchBG, null, labelRect);
context.DrawRectangle(item.LabelBG, null, labelRect);
context.DrawText(item.Label, new Point(x + 20, 8.0 - item.Label.Height * 0.5));
using (context.PushTransform(Matrix.CreateTranslation(x + 4, 4)))
@ -121,25 +138,23 @@ namespace SourceGit.Views
}
}
protected override void OnDataContextChanged(EventArgs e)
{
base.OnDataContextChanged(e);
InvalidateMeasure();
}
protected override Size MeasureOverride(Size availableSize)
{
_items.Clear();
if (DataContext is Models.Commit commit && commit.HasDecorators)
var refs = Refs;
if (refs != null && refs.Count > 0)
{
var typeface = new Typeface(FontFamily);
var typefaceBold = new Typeface(FontFamily, FontStyle.Normal, FontWeight.Bold);
var labelFG = LabelForeground;
var branchBG = BranchNameBackground;
var headBG = HeadBranchNameBackground;
var tagBG = TagNameBackground;
var labelSize = FontSize;
var requiredWidth = 0.0;
foreach (var decorator in commit.Decorators)
foreach (var decorator in refs)
{
var isHead = decorator.Type == Models.DecoratorType.CurrentBranchHead ||
decorator.Type == Models.DecoratorType.CurrentCommitHead;
@ -152,26 +167,28 @@ namespace SourceGit.Views
labelSize,
labelFG);
var item = new RenderItem()
{
Label = label,
IsTag = decorator.Type == Models.DecoratorType.Tag,
};
var item = new RenderItem() { Label = label };
StreamGeometry geo;
switch (decorator.Type)
{
case Models.DecoratorType.CurrentBranchHead:
item.LabelBG = headBG;
geo = this.FindResource("Icons.Check") as StreamGeometry;
break;
case Models.DecoratorType.CurrentCommitHead:
item.LabelBG = branchBG;
geo = this.FindResource("Icons.Check") as StreamGeometry;
break;
case Models.DecoratorType.RemoteBranchHead:
item.LabelBG = branchBG;
geo = this.FindResource("Icons.Remote") as StreamGeometry;
break;
case Models.DecoratorType.Tag:
item.LabelBG = tagBG;
geo = this.FindResource("Icons.Tag") as StreamGeometry;
break;
default:
item.LabelBG = branchBG;
geo = this.FindResource("Icons.Branch") as StreamGeometry;
break;
}

View file

@ -0,0 +1,36 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.CommitRelationTracking">
<Grid RowDefinitions="Auto,Auto,Auto">
<TextBlock Grid.Row="0" Classes="info_label" Text="{DynamicResource Text.CommitDetail.Info.ContainsIn.Title}" HorizontalAlignment="Center"/>
<Rectangle Grid.Row="1" Height="1" HorizontalAlignment="Stretch" Margin="0,8" Fill="{DynamicResource Brush.Border2}"/>
<ScrollViewer Grid.Row="2" MinWidth="300" MaxWidth="500" MaxHeight="200" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ItemsControl x:Name="Container">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="m:Decorator">
<Border Height="20" Margin="0,4,6,0" BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}" CornerRadius="12">
<StackPanel Orientation="Horizontal" Margin="8,0" VerticalAlignment="Center">
<Path Width="10" Height="10" Data="{StaticResource Icons.Branch}" IsVisible="{Binding !IsTag}"/>
<Path Width="10" Height="10" Data="{StaticResource Icons.Tag}" IsVisible="{Binding IsTag}"/>
<TextBlock Classes="primary" Text="{Binding Name}" Margin="2,0,0,0"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<v:LoadingIcon x:Name="LoadingIcon" Grid.Row="2" HorizontalAlignment="Center" Margin="0,8" Width="14" Height="14" IsVisible="False"/>
</Grid>
</UserControl>

View file

@ -0,0 +1,32 @@
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Threading;
namespace SourceGit.Views
{
public partial class CommitRelationTracking : UserControl
{
public CommitRelationTracking()
{
InitializeComponent();
}
public CommitRelationTracking(ViewModels.CommitDetail detail)
{
InitializeComponent();
LoadingIcon.IsVisible = true;
Task.Run(() =>
{
var containsIn = detail.GetRefsContainsThisCommit();
Dispatcher.UIThread.Invoke(() =>
{
Container.ItemsSource = containsIn;
LoadingIcon.IsVisible = false;
});
});
}
}
}

View file

@ -0,0 +1,65 @@
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.ConfirmRestart"
x:Name="ThisControl"
Title="Restart Required"
Icon="/App.ico"
CanResize="False"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
Margin="10,0,0,0"
Data="{StaticResource Icons.Info}"
IsVisible="{OnPlatform True, macOS=False}"/>
<Grid Grid.Column="0" Classes="caption_button_box" Margin="2,4,0,0" IsVisible="{OnPlatform False, macOS=True}">
<Button Classes="caption_button_macos" Click="CloseWindow">
<Grid>
<Ellipse Fill="{DynamicResource Brush.MacOS.Close}"/>
<Path Height="6" Width="6" Stretch="Fill" Fill="#505050" Data="{StaticResource Icons.MacOS.Close}"/>
</Grid>
</Button>
</Grid>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
Text="Restart Required"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<Button Grid.Column="2"
Classes="caption_button"
Click="CloseWindow"
IsVisible="{OnPlatform True, macOS=False}">
<Path Data="{StaticResource Icons.Window.Close}"/>
</Button>
</Grid>
<StackPanel Grid.Row="1" Margin="0,16" Orientation="Vertical">
<Border Margin="16,0">
<TextBlock Text="You need to restart this app to apply changes."/>
</Border>
<Button Classes="flat primary"
Width="80"
Margin="0,16,0,0"
Content="{DynamicResource Text.Sure}"
Click="Restart"
HorizontalAlignment="Center"
HotKey="Enter"/>
</StackPanel>
</Grid>
</v:ChromelessWindow>

View file

@ -0,0 +1,35 @@
using System;
using System.Diagnostics;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
{
public partial class ConfirmRestart : ChromelessWindow
{
public ConfirmRestart()
{
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2)
{
Console.Out.WriteLine("No passphrase entered.");
App.Quit(-1);
}
private void Restart(object _1, RoutedEventArgs _2)
{
var selfExecFile = Process.GetCurrentProcess().MainModule!.FileName;
Process.Start(selfExecFile);
App.Quit(-1);
}
}
}

View file

@ -14,7 +14,14 @@
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.CreateBranch.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32" ColumnDefinitions="140,*">
<Grid Margin="0,16,0,0" ColumnDefinitions="140,*">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="Auto" MinHeight="32"/>
<RowDefinition Height="32"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -61,23 +68,23 @@
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.CreateBranch.LocalChanges}"/>
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal">
<StackPanel.Resources>
<WrapPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<WrapPanel.Resources>
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
</StackPanel.Resources>
</WrapPanel.Resources>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.DoNothing}"
GroupName="LocalChanges"
Margin="0,0,8,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}"
GroupName="LocalChanges"
Margin="8,0,0,0"
Margin="0,0,8,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/>
<RadioButton Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}"
GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/>
</StackPanel>
</WrapPanel>
<CheckBox Grid.Row="3" Grid.Column="1"
Content="{DynamicResource Text.CreateBranch.Checkout}"

View file

@ -47,7 +47,7 @@
Command="{Binding DecrUnified}"
IsVisible="{Binding IsTextDiff}"
ToolTip.Tip="{DynamicResource Text.Diff.VisualLines.Decr}"
IsEnabled="{Binding Source={x:Static vm:Preference.Instance}, Path=DiffViewVisualLineNumbers, Converter={x:Static c:IntConverters.IsGreaterThanFour}}">
IsEnabled="{Binding UnifiedLines, Converter={x:Static c:IntConverters.IsGreaterThanFour}}">
<Path Width="12" Height="12" Stretch="Uniform" Margin="0,6,0,0" Data="{StaticResource Icons.Lines.Decr}"/>
</Button>

View file

@ -9,20 +9,20 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.FileHistories"
x:DataType="vm:FileHistories"
x:Name="me"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.FileHistory}"
MinWidth="1280" MinHeight="720">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="5"
<Border Grid.Column="0" Grid.ColumnSpan="4"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
DoubleTapped="MaximizeOrRestoreWindow"
@ -79,7 +79,14 @@
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto">
<v:Avatar Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/>
<TextBlock Grid.Column="1" Classes="primary" Text="{Binding Author.Name}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="2" Classes="primary" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
<TextBlock Grid.Column="2"
Classes="primary"
Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
Background="Transparent"
Foreground="DarkOrange"
TextDecorations="Underline"
Margin="8,0,0,0"
PointerPressed="OnPressCommitSHA"/>
<TextBlock Grid.Column="3" Classes="primary" Text="{Binding AuthorTimeShortStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
</Grid>
@ -104,41 +111,122 @@
HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsLoading}"/>
<Grid Grid.Column="2" RowDefinitions="*,3,*" IsVisible="{Binding !IsLoading}">
<ContentControl Grid.Row="0" Margin="4,4,8,0" Content="{Binding DiffContext}">
<Grid Grid.Column="2" RowDefinitions="Auto,*,Auto" IsVisible="{Binding !IsLoading}">
<ListBox Grid.Row="0"
Margin="0,8"
SelectedIndex="{Binding ViewMode, Mode=TwoWay}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Transparent"
BorderThickness="1"
BorderBrush="{DynamicResource Brush.Border2}"
CornerRadius="14"
Padding="3,0">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Height" Value="28"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="ListBoxItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="ListBoxItem:selected /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="ListBoxItem Border.switcher_bg">
<Setter Property="Height" Value="22"/>
<Setter Property="CornerRadius" Value="11"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Padding" Value="16,0"/>
</Style>
<Style Selector="ListBoxItem:selected Border.switcher_bg">
<Setter Property="Background" Value="{DynamicResource Brush.Accent}"/>
</Style>
<Style Selector="TextBlock.view_mode_switcher">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="{DynamicResource Brush.FG2}"/>
</Style>
<Style Selector="ListBoxItem:pointerover TextBlock.view_mode_switcher">
<Setter Property="Foreground" Value="{DynamicResource Brush.FG1}"/>
</Style>
<Style Selector="ListBoxItem:selected TextBlock.view_mode_switcher">
<Setter Property="Foreground" Value="White"/>
</Style>
</ListBox.Styles>
<ListBoxItem>
<Border Classes="switcher_bg">
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.FileHistory.FileChange}"/>
</Border>
</ListBoxItem>
<ListBoxItem>
<Border Classes="switcher_bg">
<TextBlock Classes="view_mode_switcher" Text="{DynamicResource Text.FileHistory.FileContent}"/>
</Border>
</ListBoxItem>
</ListBox>
<ContentControl Grid.Row="1" Margin="4,4,8,8" Content="{Binding ViewContent}">
<ContentControl.DataTemplates>
<DataTemplate DataType="vm:DiffContext">
<v:DiffView/>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
<GridSplitter Grid.Row="1"
MinHeight="1"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="Transparent"/>
<DataTemplate DataType="vm:FileHistoriesRevisionFile">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
<Grid RowDefinitions="26,*">
<Border Grid.Row="0"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
Background="{DynamicResource Brush.Window}">
<Grid ColumnDefinitions="Auto,*">
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.File}" Margin="8,0,0,0"/>
<TextBlock Grid.Column="1"
Classes="primary"
Margin="4,0,0,0"
Text="{Binding Path}"
FontSize="11"
TextTrimming="CharacterEllipsis"/>
</Grid>
</Border>
<Border Grid.Row="2" Margin="0,0,4,4">
<ContentControl>
<ContentControl.Content>
<Binding Path="DetailContext">
<Binding.TargetNullValue>
<Path Width="128" Height="128"
Data="{StaticResource Icons.Detail}"
HorizontalAlignment="Center"
Fill="{DynamicResource Brush.FG2}"/>
</Binding.TargetNullValue>
</Binding>
</ContentControl.Content>
<ContentControl.DataTemplates>
<DataTemplate DataType="vm:CommitDetail">
<v:CommitDetail/>
<v:RevisionFileContentViewer Grid.Row="1" Content="{Binding Content}"/>
</Grid>
</Border>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
<Button Grid.Row="2"
Classes="flat primary"
Margin="0,0,0,8"
HorizontalAlignment="Center"
Content="{DynamicResource Text.ChangeCM.CheckoutThisRevision}"
Click="OnResetToSelectedRevision"/>
</Grid>
</Grid>
<Border Grid.Row="1" x:Name="NotifyDonePanel" Background="Transparent" IsVisible="False" PointerPressed="OnCloseNotifyPanel">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" Effect="drop-shadow(0 0 12 #80000000)">
<Border CornerRadius="8" Background="{DynamicResource Brush.Popup}" Padding="32">
<Path Width="52" Height="52" Data="{StaticResource Icons.Check}" Fill="Green"/>
</Border>
</Border>
</Border>
</Grid>
</Grid>
</Grid>
</v:ChromelessWindow>

View file

@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
{
@ -27,5 +28,33 @@ namespace SourceGit.Views
e.Handled = true;
}
private void OnPressCommitSHA(object sender, PointerPressedEventArgs e)
{
if (sender is TextBlock { DataContext: Models.Commit commit } &&
DataContext is ViewModels.FileHistories vm)
{
vm.NavigateToCommit(commit);
}
e.Handled = true;
}
private void OnResetToSelectedRevision(object _, RoutedEventArgs e)
{
if (DataContext is ViewModels.FileHistories vm)
{
vm.ResetToSelectedRevision();
NotifyDonePanel.IsVisible = true;
}
e.Handled = true;
}
private void OnCloseNotifyPanel(object _, PointerPressedEventArgs e)
{
NotifyDonePanel.IsVisible = false;
e.Handled = true;
}
}
}

View file

@ -67,15 +67,16 @@
BehindBrush="{DynamicResource Brush.FG1}"
VerticalAlignment="Center"/>
<v:CommitRefsPresenter IsVisible="{Binding HasDecorators}"
IconBackground="{DynamicResource Brush.DecoratorIconBG}"
<v:CommitRefsPresenter IconBackground="{DynamicResource Brush.DecoratorIconBG}"
IconForeground="{DynamicResource Brush.DecoratorIcon}"
BranchNameBackground="{DynamicResource Brush.DecoratorBranch}"
HeadBranchNameBackground="{DynamicResource Brush.DecoratorHead}"
TagNameBackground="{DynamicResource Brush.DecoratorTag}"
LabelForeground="{DynamicResource Brush.DecoratorFG}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontSize="10"
VerticalAlignment="Center"/>
FontFamily="{DynamicResource Fonts.Primary}"
FontSize="11"
VerticalAlignment="Center"
Refs="{Binding Decorators}"/>
<v:CommitSubjectPresenter Classes="primary"
Subject="{Binding Subject}"

View file

@ -11,7 +11,6 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Threading;
using Avalonia.Utilities;
using Avalonia.VisualTree;
namespace SourceGit.Views
@ -185,7 +184,7 @@ namespace SourceGit.Views
if (change.Property == SubjectProperty || change.Property == IssueTrackerRulesProperty)
{
Inlines.Clear();
Inlines!.Clear();
_matches = null;
ClearHoveredIssueLink();
@ -200,7 +199,7 @@ namespace SourceGit.Views
return;
}
var matches = new List<Models.IssueTrackerMatch>();
var matches = new List<Models.Hyperlink>();
foreach (var rule in rules)
rule.Matches(matches, subject);
@ -219,9 +218,9 @@ namespace SourceGit.Views
if (match.Start > pos)
Inlines.Add(new Run(subject.Substring(pos, match.Start - pos)));
match.Link = new Run(subject.Substring(match.Start, match.Length));
match.Link.Classes.Add("issue_link");
Inlines.Add(match.Link);
var link = new Run(subject.Substring(match.Start, match.Length));
link.Classes.Add("issue_link");
Inlines.Add(link);
pos = match.Start + match.Length;
}
@ -239,11 +238,10 @@ namespace SourceGit.Views
if (_matches != null)
{
var padding = Padding;
var point = e.GetPosition(this) - new Point(padding.Left, padding.Top);
point = new Point(
MathUtilities.Clamp(point.X, 0, Math.Max(TextLayout.WidthIncludingTrailingWhitespace, 0)),
MathUtilities.Clamp(point.Y, 0, Math.Max(TextLayout.Height, 0)));
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));
var y = Math.Min(Math.Max(point.Y, 0), Math.Max(TextLayout.Height, 0));
point = new Point(x, y);
var textPosition = TextLayout.HitTestPoint(point).TextPosition;
foreach (var match in _matches)
@ -255,10 +253,8 @@ namespace SourceGit.Views
return;
_lastHover = match;
//_lastHover.Link.Classes.Add("issue_link_hovered");
SetCurrentValue(CursorProperty, Cursor.Parse("Hand"));
ToolTip.SetTip(this, match.URL);
ToolTip.SetTip(this, match.Link);
ToolTip.SetIsOpen(this, true);
e.Handled = true;
return;
@ -273,7 +269,7 @@ namespace SourceGit.Views
base.OnPointerPressed(e);
if (_lastHover != null)
Native.OS.OpenBrowser(_lastHover.URL);
Native.OS.OpenBrowser(_lastHover.Link);
}
protected override void OnPointerExited(PointerEventArgs e)
@ -288,13 +284,12 @@ namespace SourceGit.Views
{
ToolTip.SetTip(this, null);
SetCurrentValue(CursorProperty, Cursor.Parse("Arrow"));
//_lastHover.Link.Classes.Remove("issue_link_hovered");
_lastHover = null;
}
}
private List<Models.IssueTrackerMatch> _matches = null;
private Models.IssueTrackerMatch _lastHover = null;
private List<Models.Hyperlink> _matches = null;
private Models.Hyperlink _lastHover = null;
}
public class CommitTimeTextBlock : TextBlock
@ -479,25 +474,14 @@ namespace SourceGit.Views
var top = startY;
var bottom = startY + grid.Bounds.Height + rowHeight * 2;
// Draw all curves
DrawCurves(context, top, bottom);
// Draw connect dots
IBrush dotFill = DotBrush;
foreach (var dot in graph.Dots)
{
if (dot.Center.Y < top)
continue;
if (dot.Center.Y > bottom)
break;
context.DrawEllipse(dotFill, Models.CommitGraph.Pens[dot.Color], dot.Center, 3, 3);
}
// Draw contents
DrawCurves(context, graph, top, bottom);
DrawAnchors(context, graph, top, bottom);
}
private void DrawCurves(DrawingContext context, double top, double bottom)
private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom)
{
foreach (var line in Graph.Paths)
foreach (var line in graph.Paths)
{
var last = line.Points[0];
var size = line.Points.Count;
@ -565,7 +549,7 @@ namespace SourceGit.Views
context.DrawGeometry(null, pen, geo);
}
foreach (var link in Graph.Links)
foreach (var link in graph.Links)
{
if (link.End.Y < top)
continue;
@ -582,6 +566,37 @@ namespace SourceGit.Views
context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo);
}
}
private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom)
{
IBrush dotFill = DotBrush;
Pen dotFillPen = new Pen(dotFill, 2);
foreach (var dot in graph.Dots)
{
if (dot.Center.Y < top)
continue;
if (dot.Center.Y > bottom)
break;
var pen = Models.CommitGraph.Pens[dot.Color];
switch (dot.Type)
{
case Models.CommitGraph.DotType.Head:
context.DrawEllipse(dotFill, pen, dot.Center, 6, 6);
context.DrawEllipse(pen.Brush, null, dot.Center, 3, 3);
break;
case Models.CommitGraph.DotType.Merge:
context.DrawEllipse(pen.Brush, null, dot.Center, 6, 6);
context.DrawLine(dotFillPen, new Point(dot.Center.X, dot.Center.Y - 3), new Point(dot.Center.X, dot.Center.Y + 3));
context.DrawLine(dotFillPen, new Point(dot.Center.X - 3, dot.Center.Y), new Point(dot.Center.X + 3, dot.Center.Y));
break;
default:
context.DrawEllipse(dotFill, pen, dot.Center, 3, 3);
break;
}
}
}
}
public partial class Histories : UserControl

View file

@ -7,6 +7,7 @@
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.Hotkeys"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.Hotkeys}"
SizeToContent="WidthAndHeight"
@ -14,7 +15,7 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -9,13 +9,14 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.InteractiveRebase"
x:DataType="vm:InteractiveRebase"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.InteractiveRebase}"
Width="1080" Height="720"
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,*,Auto">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -7,13 +7,14 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.LFSLocks"
x:DataType="vm:LFSLocks"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.GitLFS.Locks.Title}"
Width="600" Height="400"
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -8,13 +8,14 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.Launcher"
x:DataType="vm:Launcher"
x:Name="ThisControl"
Icon="/App.ico"
Title="SourceGit"
MinWidth="1024" MinHeight="600"
WindowStartupLocation="CenterScreen">
<Grid x:Name="MainLayout">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="38"/>
<RowDefinition Height="{Binding #ThisControl.CaptionHeight}"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
@ -72,7 +73,7 @@
<v:LauncherTabBar Grid.Column="1" Height="30" VerticalAlignment="Bottom"/>
<!-- Caption Buttons (Windows/Linux)-->
<Border Grid.Column="2" Margin="32,0,0,0" IsVisible="{OnPlatform True, macOS=False}">
<Border Grid.Column="2" Margin="32,0,0,0" IsVisible="{Binding #ThisControl.IsRightCaptionButtonsVisible}">
<v:CaptionButtons Height="30" VerticalAlignment="Top"/>
</Border>
</Grid>

View file

@ -3,11 +3,31 @@ using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.VisualTree;
namespace SourceGit.Views
{
public partial class Launcher : ChromelessWindow
{
public static readonly StyledProperty<GridLength> CaptionHeightProperty =
AvaloniaProperty.Register<Launcher, GridLength>(nameof(CaptionHeight));
public GridLength CaptionHeight
{
get => GetValue(CaptionHeightProperty);
set => SetValue(CaptionHeightProperty, value);
}
public bool IsRightCaptionButtonsVisible
{
get
{
if (OperatingSystem.IsLinux())
return !ViewModels.Preference.Instance.UseSystemWindowFrame;
return OperatingSystem.IsWindows();
}
}
public Launcher()
{
var layout = ViewModels.Preference.Instance.Layout;
@ -17,6 +37,11 @@ namespace SourceGit.Views
Height = layout.LauncherHeight;
}
if (UseSystemWindowFrame)
CaptionHeight = new GridLength(30);
else
CaptionHeight = new GridLength(38);
InitializeComponent();
}
@ -38,13 +63,15 @@ namespace SourceGit.Views
{
base.OnPropertyChanged(change);
if (change.Property == WindowStateProperty && MainLayout != null)
if (change.Property == WindowStateProperty)
{
var state = (WindowState)change.NewValue!;
if (state == WindowState.Maximized)
MainLayout.RowDefinitions[0].Height = new GridLength(OperatingSystem.IsMacOS() ? 34 : 30);
if (OperatingSystem.IsLinux() && UseSystemWindowFrame)
CaptionHeight = new GridLength(30);
else if (state == WindowState.Maximized)
CaptionHeight = new GridLength(OperatingSystem.IsMacOS() ? 34 : 30);
else
MainLayout.RowDefinitions[0].Height = new GridLength(38);
CaptionHeight = new GridLength(38);
ViewModels.Preference.Instance.Layout.LauncherWindowState = state;
}
@ -59,7 +86,7 @@ namespace SourceGit.Views
// 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)
{
App.OpenPreferenceCommand.Execute(null);
App.OpenDialog(new Preference());
e.Handled = true;
return;
}
@ -134,6 +161,19 @@ namespace SourceGit.Views
return;
}
}
else
{
var welcome = this.FindDescendantOfType<Welcome>();
if (welcome != null)
{
if (e.Key == Key.F)
{
welcome.SearchBox.Focus();
e.Handled = true;
return;
}
}
}
}
else if (e.Key == Key.Escape)
{

View file

@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:m="using:SourceGit.Models"
xmlns:c="using:SourceGit.Converters"
xmlns:vm="using:SourceGit.ViewModels"
@ -13,12 +12,12 @@
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.Preference}"
Width="600" SizeToContent="Height"
SizeToContent="WidthAndHeight"
CanResize="False"
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,Auto">
<Grid RowDefinitions="Auto,Auto" MinWidth="600">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
@ -57,7 +56,7 @@
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/>
</TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32" ColumnDefinitions="Auto,*">
<Grid Margin="8" RowDefinitions="32,32,32,32,32" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.Locale}"
HorizontalAlignment="Right"
@ -71,23 +70,10 @@
SelectedItem="{Binding Locale, Mode=TwoWay, Converter={x:Static c:StringConverters.ToLocale}}"/>
<TextBlock Grid.Row="1" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.VisibleDiffContextLines}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<NumericUpDown Grid.Row="1" Grid.Column="1"
Minimum="4" Maximum="10000" Increment="1"
Height="28"
Padding="4"
ShowButtonSpinner="False"
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
CornerRadius="3"
Value="{Binding DiffViewVisualLineNumbers, Mode=TwoWay}"/>
<TextBlock Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.SubjectGuideLength}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<NumericUpDown Grid.Row="2" Grid.Column="1"
<NumericUpDown Grid.Row="1" Grid.Column="1"
Minimum="50" Maximum="1000" Increment="1"
Height="28"
Padding="4"
@ -96,11 +82,11 @@
CornerRadius="3"
Value="{Binding SubjectGuideLength, Mode=TwoWay}"/>
<TextBlock Grid.Row="3" Grid.Column="0"
<TextBlock Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.MaxHistoryCommits}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<Grid Grid.Row="3" Grid.Column="1" ColumnDefinitions="*,64">
<Grid Grid.Row="2" Grid.Column="1" ColumnDefinitions="*,64">
<Slider Grid.Column="0"
Minimum="20000" Maximum="100000"
TickPlacement="BottomRight" TickFrequency="5000"
@ -115,16 +101,11 @@
Text="{Binding MaxHistoryCommits}"/>
</Grid>
<CheckBox Grid.Row="4" Grid.Column="1"
<CheckBox Grid.Row="3" Grid.Column="1"
Content="{DynamicResource Text.Preference.General.RestoreTabs}"
IsChecked="{Binding RestoreTabs, Mode=TwoWay}"/>
<CheckBox Grid.Row="5" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preference.General.UseFixedTabWidth}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFixedTabWidth, Mode=TwoWay}"/>
<CheckBox Grid.Row="6" Grid.Column="1"
<CheckBox Grid.Row="4" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=Check4UpdatesOnStartup, Mode=TwoWay}"/>
@ -135,7 +116,7 @@
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.Appearance}"/>
</TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32" ColumnDefinitions="Auto,*">
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.Appearance.Theme}"
HorizontalAlignment="Right"
@ -157,39 +138,19 @@
Text="{DynamicResource Text.Preference.Appearance.DefaultFont}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<ComboBox Grid.Row="1" Grid.Column="1"
MinHeight="28"
Padding="8,0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding #ThisControl.InstalledFonts}"
SelectedItem="{Binding DefaultFont, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="FontFamily">
<Border Height="24">
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" FontFamily="{Binding}"/>
</Border>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Grid.Row="1" Grid.Column="1"
Height="28"
CornerRadius="3"
Text="{Binding DefaultFontFamily, Mode=TwoWay}"/>
<TextBlock Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Preference.Appearance.MonospaceFont}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<ComboBox Grid.Row="2" Grid.Column="1"
MinHeight="28"
Padding="8,0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding #ThisControl.InstalledMonospaceFonts}"
SelectedItem="{Binding MonospaceFont, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="FontFamily">
<Border Height="24">
<TextBlock VerticalAlignment="Center" Text="{Binding Name}" FontFamily="{Binding}"/>
</Border>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Grid.Row="2" Grid.Column="1"
Height="28"
CornerRadius="3"
Text="{Binding MonospaceFontFamily, Mode=TwoWay}"/>
<TextBlock Grid.Row="3" Grid.Column="0"
Text="{DynamicResource Text.Preference.Appearance.DefaultFontSize}"
@ -221,6 +182,18 @@
<CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.Preference.Appearance.OnlyUseMonoFontInEditor}"
IsChecked="{Binding OnlyUseMonoFontInEditor, Mode=TwoWay}"/>
<CheckBox Grid.Row="6" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preference.Appearance.UseFixedTabWidth}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseFixedTabWidth, Mode=TwoWay}"/>
<CheckBox Grid.Row="7" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Preference.Appearance.UseNativeWindowFrame}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSystemWindowFrame, Mode=OneTime}"
IsVisible="{OnPlatform False, Linux=True}"
IsCheckedChanged="OnUseNativeWindowFrameChanged"/>
</Grid>
</TabItem>

View file

@ -1,30 +1,16 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
namespace SourceGit.Views
{
public partial class Preference : ChromelessWindow
{
public AvaloniaList<FontFamily> InstalledFonts
{
get;
}
public AvaloniaList<FontFamily> InstalledMonospaceFonts
{
get;
}
public string DefaultUser
{
get;
@ -93,51 +79,6 @@ namespace SourceGit.Views
var pref = ViewModels.Preference.Instance;
DataContext = pref;
var builtInMono = new FontFamily("fonts:SourceGit#JetBrains Mono");
InstalledFonts = new AvaloniaList<FontFamily>();
InstalledFonts.Add(builtInMono);
InstalledFonts.AddRange(FontManager.Current.SystemFonts);
InstalledMonospaceFonts = new AvaloniaList<FontFamily>();
InstalledMonospaceFonts.Add(builtInMono);
var curMonoFont = pref.MonospaceFont;
if (curMonoFont != builtInMono)
{
InstalledMonospaceFonts.Add(curMonoFont);
}
Task.Run(() =>
{
var sysMonoFonts = new List<FontFamily>();
foreach (var font in FontManager.Current.SystemFonts)
{
if (font == curMonoFont)
continue;
var typeface = new Typeface(font);
var testI = new FormattedText(
"i",
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
typeface,
12,
Brushes.White);
var testW = new FormattedText(
"W",
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
typeface,
12,
Brushes.White);
if (Math.Abs(testI.Width - testW.Width) < 0.0001)
sysMonoFonts.Add(font);
}
Dispatcher.UIThread.Post(() => InstalledMonospaceFonts.AddRange(sysMonoFonts));
});
var ver = string.Empty;
if (pref.IsGitConfigured())
{
@ -307,5 +248,19 @@ namespace SourceGit.Views
if (changed)
new Commands.Config(null).Set(key, value);
}
private void OnUseNativeWindowFrameChanged(object sender, RoutedEventArgs e)
{
if (sender is CheckBox box)
{
ViewModels.Preference.Instance.UseSystemWindowFrame = box.IsChecked == true;
ViewModels.Preference.Instance.Save();
var dialog = new ConfirmRestart();
App.OpenDialog(dialog);
}
e.Handled = true;
}
}
}

View file

@ -12,7 +12,17 @@
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.Pull.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32,32,32,32" ColumnDefinitions="140,*">
<Grid Margin="0,16,0,0" ColumnDefinitions="140,*">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="Auto" MinHeight="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -66,23 +76,23 @@
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
Text="{DynamicResource Text.Pull.LocalChanges}"/>
<StackPanel Grid.Row="3" Grid.Column="1" Orientation="Horizontal">
<StackPanel.Resources>
<WrapPanel Grid.Row="3" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<WrapPanel.Resources>
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
</StackPanel.Resources>
</WrapPanel.Resources>
<RadioButton Content="{DynamicResource Text.Pull.LocalChanges.DoNothing}"
Margin="0,0,8,0"
GroupName="LocalChanges"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.DoNothing}}"/>
<RadioButton Content="{DynamicResource Text.Pull.LocalChanges.StashAndReply}"
Margin="0,0,8,0"
GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.StashAndReaply}}"/>
<RadioButton Content="{DynamicResource Text.Pull.LocalChanges.Discard}"
GroupName="LocalChanges"
Margin="8,0,0,0"
IsChecked="{Binding PreAction, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:DealWithLocalChanges.Discard}}"/>
</StackPanel>
</WrapPanel>
<CheckBox Grid.Row="4" Grid.Column="1"
Content="{DynamicResource Text.Pull.FetchAllBranches}"

View file

@ -12,7 +12,7 @@
Classes="bold"
Text="{DynamicResource Text.Push.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,32,32" ColumnDefinitions="150,*">
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,Auto,Auto,32,32" ColumnDefinitions="130,*">
<TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0"
@ -78,10 +78,16 @@
IsVisible="{Binding IsSetTrackOptionVisible}"/>
<CheckBox Grid.Row="4" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Push.CheckSubmodules}"
IsChecked="{Binding CheckSubmodules, Mode=TwoWay}"
IsVisible="{Binding IsCheckSubmodulesVisible}"/>
<CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.Push.WithAllTags}"
IsChecked="{Binding PushAllTags, Mode=TwoWay}"/>
<CheckBox Grid.Row="5" Grid.Column="1"
<CheckBox Grid.Row="6" Grid.Column="1"
Content="{DynamicResource Text.Push.Force}"
IsChecked="{Binding ForcePush, Mode=TwoWay}"/>
</Grid>

View file

@ -17,7 +17,7 @@
</Grid.ColumnDefinitions>
<!-- Left Panel -->
<Grid Grid.Column="0" Classes="repository_leftpanel" RowDefinitions="Auto,*">
<Grid Grid.Column="0" RowDefinitions="Auto,*">
<!-- Page Switcher for Left Contents (Dashboard or CommitSearch) -->
<Grid Grid.Row="0" Height="24" Margin="0,6" HorizontalAlignment="Center" ColumnDefinitions="48,1,48">
<Border Grid.Column="0" Grid.ColumnSpan="3"
@ -76,7 +76,7 @@
</ListBox.ItemsPanel>
<ListBoxItem>
<Grid Classes="view_mode" ColumnDefinitions="32,*,Auto">
<Grid Classes="view_mode" ColumnDefinitions="32,*,Auto,Auto">
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Histories}"/>
<TextBlock Grid.Column="1" Classes="primary" Text="{DynamicResource Text.Histories}"/>
<ToggleButton Grid.Column="2"
@ -84,6 +84,14 @@
Width="32" Height="26"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=UseTwoColumnsLayoutInHistories, Mode=TwoWay}"
ToolTip.Tip="{DynamicResource Text.Histories.DisplayMode}"/>
<ToggleButton Grid.Column="3"
Classes="line_path"
Width="32" Height="26"
Background="Transparent"
IsChecked="{Binding EnableFirstParentInHistories, Mode=TwoWay}"
ToolTip.Tip="{DynamicResource Text.Repository.FirstParentFilterToggle}">
<Path Width="12" Height="12" Data="{StaticResource Icons.FirstParentFilter}"/>
</ToggleButton>
</Grid>
</ListBoxItem>
@ -95,7 +103,7 @@
Margin="6,0"
VerticalAlignment="Center"
Count="{Binding LocalChangesCount}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="10"
Foreground="{DynamicResource Brush.BadgeFG}"
Background="{DynamicResource Brush.Badge}"/>
@ -110,7 +118,7 @@
Margin="6,0"
VerticalAlignment="Center"
Count="{Binding StashesCount}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontFamily="{DynamicResource Fonts.Monospace}"
FontSize="10"
Foreground="{DynamicResource Brush.BadgeFG}"
Background="{DynamicResource Brush.Badge}"/>
@ -240,70 +248,36 @@
</Button>
</Grid>
</ToggleButton>
<DataGrid Grid.Row="7"
<ListBox Grid.Row="7"
x:Name="SubmoduleList"
Height="0"
Margin="8,0,4,0"
Background="Transparent"
Classes="repo_left_content_list"
ItemsSource="{Binding Submodules}"
SelectionMode="Single"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
IsReadOnly="True"
HeadersVisibility="None"
Focusable="False"
RowHeight="24"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
ContextRequested="OnSubmoduleContextRequested"
DoubleTapped="OnDoubleTappedSubmodule"
PropertyChanged="OnLeftSidebarDataGridPropertyChanged"
IsVisible="{Binding IsSubmoduleGroupExpanded, Mode=OneWay}">
<DataGrid.Styles>
<Style Selector="DataGridRow">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Height" Value="24"/>
</Style>
<Style Selector="DataGridRow /template/ Border#RowBorder">
<Setter Property="ClipToBounds" Value="True" />
</Style>
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
</Style>
<Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
</Style>
</DataGrid.Styles>
<DataGrid.Columns>
<DataGridTemplateColumn Header="ICON">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Path Width="10" Height="10" Margin="8,0" Data="{StaticResource Icons.Submodule}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="NAME">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Background="Transparent" Margin="0,0,4,0" ColumnDefinitions="*,8">
<TextBlock Grid.Column="0" Text="{Binding Path}" ClipToBounds="True" Classes="primary" TextTrimming="CharacterEllipsis"/>
<Path Grid.Column="1"
</ListBox.Styles>
<ListBox.ItemTemplate>
<DataTemplate DataType="m:Submodule">
<Grid ColumnDefinitions="Auto,*,8">
<Path Grid.Column="0" Width="10" Height="10" Margin="8,0" Data="{StaticResource Icons.Submodule}"/>
<TextBlock Grid.Column="1" Text="{Binding Path}" ClipToBounds="True" Classes="primary" TextTrimming="CharacterEllipsis"/>
<Path Grid.Column="2"
Width="8" Height="8"
Fill="Goldenrod"
Data="{StaticResource Icons.Modified}"
IsVisible="{Binding IsDirty}"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</ListBox.ItemTemplate>
</ListBox>
<!-- Worktrees -->
<ToggleButton Grid.Row="8" Classes="group_expander" IsChecked="{Binding IsWorktreeGroupExpanded, Mode=TwoWay}">
@ -329,74 +303,35 @@
</Button>
</Grid>
</ToggleButton>
<DataGrid Grid.Row="9"
<ListBox Grid.Row="9"
x:Name="WorktreeList"
Height="0"
Margin="8,0,4,0"
Background="Transparent"
Classes="repo_left_content_list"
ItemsSource="{Binding Worktrees}"
SelectionMode="Single"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
IsReadOnly="True"
HeadersVisibility="None"
Focusable="False"
RowHeight="24"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
ContextRequested="OnWorktreeContextRequested"
DoubleTapped="OnDoubleTappedWorktree"
PropertyChanged="OnLeftSidebarDataGridPropertyChanged"
IsVisible="{Binding IsWorktreeGroupExpanded, Mode=OneWay}">
<DataGrid.Styles>
<Style Selector="DataGridRow">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Height" Value="24"/>
</Style>
<Style Selector="DataGridRow /template/ Border#RowBorder">
<Setter Property="ClipToBounds" Value="True" />
</Style>
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
</Style>
<Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
</Style>
</DataGrid.Styles>
<DataGrid.Columns>
<DataGridTemplateColumn Header="ICON">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Path Width="10" Height="10" Margin="8,0,0,0" Data="{StaticResource Icons.Worktree}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="FullPath">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Classes="primary" Margin="8,0,0,0" TextTrimming="CharacterEllipsis">
</ListBox.Styles>
<ListBox.ItemTemplate>
<DataTemplate DataType="m:Worktree">
<Grid ColumnDefinitions="Auto,*,22">
<Path Grid.Column="0" Width="10" Height="10" Margin="8,0,0,0" Data="{StaticResource Icons.Worktree}"/>
<TextBlock Grid.Column="1" Classes="primary" Margin="8,0,0,0" TextTrimming="CharacterEllipsis">
<Run Text="{Binding FullPath}"/>
<Run Text="{Binding Name}" Foreground="{DynamicResource Brush.FG2}"/>
</TextBlock>
<Path Grid.Column="2" Width="10" Height="10" Margin="4,0,0,0" Data="{StaticResource Icons.Lock}" Fill="{DynamicResource Brush.FG2}" IsVisible="{Binding IsLocked}"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="FullPath">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Path Width="10" Height="10" Margin="4,0,8,0" Data="{StaticResource Icons.Lock}" Fill="{DynamicResource Brush.FG2}" IsVisible="{Binding IsLocked}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>

View file

@ -63,11 +63,6 @@ namespace SourceGit.Views
FontFamilyProperty,
ForegroundProperty,
CountProperty);
AffectsRender<CounterPresenter>(
ForegroundProperty,
BackgroundProperty,
CountProperty);
}
public override void Render(DrawingContext context)
@ -98,6 +93,7 @@ namespace SourceGit.Views
_label = null;
}
InvalidateVisual();
return _label != null ? new Size(_label.Width + 18, 18) : new Size(0, 0);
}
@ -200,7 +196,7 @@ namespace SourceGit.Views
private void OnSubmoduleContextRequested(object sender, ContextRequestedEventArgs e)
{
if (sender is DataGrid { SelectedItem: Models.Submodule submodule } grid && DataContext is ViewModels.Repository repo)
if (sender is ListBox { SelectedItem: Models.Submodule submodule } grid && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForSubmodule(submodule.Path);
grid.OpenContextMenu(menu);
@ -211,7 +207,7 @@ namespace SourceGit.Views
private void OnDoubleTappedSubmodule(object sender, TappedEventArgs e)
{
if (sender is DataGrid { SelectedItem: Models.Submodule submodule } && DataContext is ViewModels.Repository repo)
if (sender is ListBox { SelectedItem: Models.Submodule submodule } && DataContext is ViewModels.Repository repo)
{
repo.OpenSubmodule(submodule.Path);
}
@ -221,7 +217,7 @@ namespace SourceGit.Views
private void OnWorktreeContextRequested(object sender, ContextRequestedEventArgs e)
{
if (sender is DataGrid { SelectedItem: Models.Worktree worktree } grid && DataContext is ViewModels.Repository repo)
if (sender is ListBox { SelectedItem: Models.Worktree worktree } grid && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForWorktree(worktree);
grid.OpenContextMenu(menu);
@ -232,7 +228,7 @@ namespace SourceGit.Views
private void OnDoubleTappedWorktree(object sender, TappedEventArgs e)
{
if (sender is DataGrid { SelectedItem: Models.Worktree worktree } && DataContext is ViewModels.Repository repo)
if (sender is ListBox { SelectedItem: Models.Worktree worktree } && DataContext is ViewModels.Repository repo)
{
repo.OpenWorktree(worktree);
}
@ -242,7 +238,7 @@ namespace SourceGit.Views
private void OnLeftSidebarDataGridPropertyChanged(object _, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == DataGrid.ItemsSourceProperty || e.Property == DataGrid.IsVisibleProperty)
if (e.Property == ListBox.ItemsSourceProperty || e.Property == ListBox.IsVisibleProperty)
UpdateLeftSidebarLayout();
}
@ -266,8 +262,8 @@ namespace SourceGit.Views
var remoteBranchRows = vm.IsRemoteGroupExpanded ? RemoteBranchTree.Rows.Count : 0;
var desiredBranches = (localBranchRows + remoteBranchRows) * 24.0;
var desiredTag = vm.IsTagGroupExpanded ? 24.0 * TagsList.Rows : 0;
var desiredSubmodule = vm.IsSubmoduleGroupExpanded ? SubmoduleList.RowHeight * vm.Submodules.Count : 0;
var desiredWorktree = vm.IsWorktreeGroupExpanded ? WorktreeList.RowHeight * vm.Worktrees.Count : 0;
var desiredSubmodule = vm.IsSubmoduleGroupExpanded ? 24.0 * vm.Submodules.Count : 0;
var desiredWorktree = vm.IsWorktreeGroupExpanded ? 24.0 * vm.Worktrees.Count : 0;
var desiredOthers = desiredTag + desiredSubmodule + desiredWorktree;
var hasOverflow = (desiredBranches + desiredOthers > leftHeight);

View file

@ -8,14 +8,15 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.RepositoryConfigure"
x:DataType="vm:RepositoryConfigure"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.Configure}"
Width="600" SizeToContent="Height"
CanResize="False"
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,Auto">
<Grid RowDefinitions="Auto,Auto">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -0,0 +1,58 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.RevisionFileContentViewer">
<UserControl.DataTemplates>
<DataTemplate DataType="m:RevisionBinaryFile">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path Width="64" Height="64" Data="{StaticResource Icons.Error}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Margin="0,16,0,0" Text="{DynamicResource Text.BinaryNotSupported}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<StackPanel Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Classes="primary" Text="{Binding Size}" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Text="{DynamicResource Text.Bytes}" Margin="8,0,0,0" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="m:RevisionTextFile">
<v:RevisionTextFileView FontFamily="{DynamicResource Fonts.Monospace}" Background="{DynamicResource Brush.Contents}"/>
</DataTemplate>
<DataTemplate DataType="m:RevisionImageFile">
<Border Margin="0,8" VerticalAlignment="Center" HorizontalAlignment="Center" Effect="drop-shadow(0 0 8 #A0000000)">
<Border Background="{DynamicResource Brush.Window}">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Margin="8">
<Grid>
<v:ImageContainer/>
<Image Source="{Binding Image}" Stretch="Uniform" VerticalAlignment="Center" RenderOptions.BitmapInterpolationMode="HighQuality"/>
</Grid>
</Border>
</Border>
</Border>
</DataTemplate>
<DataTemplate DataType="m:RevisionLFSObject">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{DynamicResource Text.CommitDetail.Files.LFS}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<Path Width="64" Height="64" Margin="0,24,0,0" Data="{StaticResource Icons.LFS}" Fill="{DynamicResource Brush.FG2}"/>
<SelectableTextBlock Margin="0,16,0,0" Text="{Binding Object.Oid}" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<StackPanel Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Classes="primary" Text="{Binding Object.Size}" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Text="{DynamicResource Text.Bytes}" Margin="8,0,0,0" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="m:RevisionSubmodule">
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Margin="8,8,8,0">
<TextBlock Text="{DynamicResource Text.CommitDetail.Files.Submodule}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<v:CommitBaseInfo Margin="0,16,0,0" Content="{Binding Commit}" Message="{Binding FullMessage}"/>
</StackPanel>
</DataTemplate>
</UserControl.DataTemplates>
</UserControl>

View file

@ -0,0 +1,13 @@
using Avalonia.Controls;
namespace SourceGit.Views
{
public partial class RevisionFileContentViewer : UserControl
{
public RevisionFileContentViewer()
{
InitializeComponent();
}
}
}

View file

@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
@ -28,56 +27,7 @@
<!-- File Content Viewer -->
<Grid Grid.Column="2">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
<ContentControl Content="{Binding ViewRevisionFileContent}">
<ContentControl.DataTemplates>
<DataTemplate DataType="m:RevisionBinaryFile">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path Width="64" Height="64" Data="{StaticResource Icons.Error}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Margin="0,16,0,0" Text="{DynamicResource Text.BinaryNotSupported}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<StackPanel Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Classes="primary" Text="{Binding Size}" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Text="{DynamicResource Text.Bytes}" Margin="8,0,0,0" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="m:RevisionTextFile">
<v:RevisionTextFileView FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}" Background="{DynamicResource Brush.Contents}"/>
</DataTemplate>
<DataTemplate DataType="m:RevisionImageFile">
<Border Margin="0,8" VerticalAlignment="Center" HorizontalAlignment="Center" Effect="drop-shadow(0 0 8 #A0000000)">
<Border Background="{DynamicResource Brush.Window}">
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}" Margin="8">
<Grid>
<v:ImageContainer/>
<Image Source="{Binding Image}" Stretch="Uniform" VerticalAlignment="Center" RenderOptions.BitmapInterpolationMode="HighQuality"/>
</Grid>
</Border>
</Border>
</Border>
</DataTemplate>
<DataTemplate DataType="m:RevisionLFSObject">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{DynamicResource Text.CommitDetail.Files.LFS}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<Path Width="64" Height="64" Margin="0,24,0,0" Data="{StaticResource Icons.LFS}" Fill="{DynamicResource Brush.FG2}"/>
<SelectableTextBlock Margin="0,16,0,0" Text="{Binding Object.Oid}" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<StackPanel Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Classes="primary" Text="{Binding Object.Size}" Foreground="{DynamicResource Brush.FG2}"/>
<TextBlock Text="{DynamicResource Text.Bytes}" Margin="8,0,0,0" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="m:RevisionSubmodule">
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Margin="8,8,8,0">
<TextBlock Text="{DynamicResource Text.CommitDetail.Files.Submodule}" FontSize="18" FontWeight="Bold" HorizontalAlignment="Center" Foreground="{DynamicResource Brush.FG2}"/>
<v:CommitBaseInfo Margin="0,16,0,0" Content="{Binding Commit}" Message="{Binding FullMessage}"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
<v:RevisionFileContentViewer Content="{Binding ViewRevisionFileContent}"/>
</Border>
</Grid>
</Grid>

View file

@ -9,6 +9,7 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.SelfUpdate"
x:DataType="vm:SelfUpdate"
x:Name="ThisControl"
Title="{DynamicResource Text.SelfUpdate.Title}"
Icon="/App.ico"
SizeToContent="WidthAndHeight"
@ -16,7 +17,7 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -13,30 +13,19 @@
Classes="bold"
Text="{DynamicResource Text.Squash}"/>
<Grid Margin="0,18,0,0" ColumnDefinitions="Auto,Auto,Auto,Auto,*">
<Border Grid.Column="0" Background="{DynamicResource Brush.Accent}" CornerRadius="4">
<TextBlock Text="HEAD" Classes="primary" Margin="4,0" Foreground="#FFDDDDDD"/>
</Border>
<Grid Margin="0,18,0,0" ColumnDefinitions="Auto,Auto,Auto,*">
<TextBlock Grid.Column="0"
Text="{DynamicResource Text.Squash.Into}"/>
<Path Grid.Column="1"
Width="14" Height="14"
Margin="12,0,0,0"
Fill="{DynamicResource Brush.FG1}"
Data="{StaticResource Icons.Down}"
VerticalAlignment="Center"
RenderTransformOrigin="50%,50%"
RenderTransform="rotate(270deg)"/>
<Path Grid.Column="2"
Margin="6,6,8,0"
Margin="8,6,8,0"
Width="14" Height="14"
Fill="{DynamicResource Brush.FG1}"
Data="{StaticResource Icons.Commit}"/>
<TextBlock Grid.Column="3"
<TextBlock Grid.Column="2"
Classes="primary"
Text="{Binding Parent.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
Text="{Binding Target.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}"
Foreground="DarkOrange"/>
<TextBlock Grid.Column="4" Margin="8,0,0,0" Text="{Binding Parent.Subject}" TextTrimming="CharacterEllipsis"/>
<TextBlock Grid.Column="3" Margin="8,0,0,0" Text="{Binding Target.Subject}" TextTrimming="CharacterEllipsis"/>
</Grid>
<v:CommitMessageTextBox Height="120" Margin="0,4,0,0" Text="{Binding Message, Mode=TwoWay}"/>

View file

@ -5,6 +5,7 @@
xmlns:v="using:SourceGit.Views"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.StandaloneCommitMessageEditor"
x:Name="ThisControl"
Icon="/App.ico"
Title="{DynamicResource Text.CodeEditor}"
Width="800"
@ -13,7 +14,7 @@
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -8,13 +8,14 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.Statistics"
x:DataType="vm:Statistics"
x:Name="ThisControl"
Title="{DynamicResource Text.Statistics}"
Width="800" Height="450"
WindowStartupLocation="CenterOwner"
CanResize="False">
<Grid RowDefinitions="Auto,Auto,*">
<!-- Title bar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"

View file

@ -86,7 +86,8 @@ namespace SourceGit.Views
else
maxV = (int)Math.Ceiling(maxV / 500.0) * 500;
var typeface = new Typeface("fonts:SourceGit#JetBrains Mono");
var fontFamily = this.FindResource("Fonts.Monospace") as FontFamily;
var typeface = new Typeface(fontFamily);
var pen = new Pen(LineBrush);
var width = Bounds.Width;
var height = Bounds.Height;

View file

@ -9,28 +9,15 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.TagsView">
<UserControl.Styles>
<Style Selector="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ItemsPanel">
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</Setter>
</Style>
<Style Selector="ListBoxItem">
<Setter Property="Height" Value="24"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
</UserControl.Styles>
<UserControl.DataTemplates>
<DataTemplate DataType="vm:TagCollectionAsTree">
<ListBox ItemsSource="{Binding Rows}"
<ListBox Classes="repo_left_content_list"
ItemsSource="{Binding Rows}"
SelectionMode="Single"
SelectionChanged="OnRowSelectionChanged">
<ListBox.ItemTemplate>
@ -70,7 +57,8 @@
</DataTemplate>
<DataTemplate DataType="vm:TagCollectionAsList">
<ListBox ItemsSource="{Binding Tags}"
<ListBox Classes="repo_left_content_list"
ItemsSource="{Binding Tags}"
SelectionMode="Single"
SelectionChanged="OnRowSelectionChanged">
<ListBox.ItemTemplate>

View file

@ -282,6 +282,7 @@ namespace SourceGit.Views
var tags = Tags;
if (tags == null || tags.Count == 0)
{
Rows = 0;
Content = null;
return;
}

View file

@ -22,7 +22,7 @@
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontFamily="{DynamicResource Fonts.Monospace}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
@ -43,7 +43,7 @@
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontFamily="{DynamicResource Fonts.Monospace}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"
@ -63,7 +63,7 @@
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
IndicatorForeground="{DynamicResource Brush.FG2}"
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
FontFamily="{DynamicResource Fonts.Monospace}"
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
ShowHiddenSymbols="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowHiddenSymbolsInDiffView}"

Some files were not shown because too many files have changed in this diff Show more