Compare commits

...

12 commits

Author SHA1 Message Date
leo
7a02854e2d
fix: bad output file name while creating archive by tag
Some checks failed
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Has been cancelled
2024-12-31 11:19:05 +08:00
leo
87e7b792bb
refactor: date time format
- generate example dynamically
- update commit/author time in histories immediately after data time format changed
2024-12-31 10:43:00 +08:00
leo
a6420aff9b
fix: crash if the executable file can not be found 2024-12-31 09:38:46 +08:00
wl2776
addc756fbf
feature: support several more variants of git installation on MacOS (#852) 2024-12-31 09:28:00 +08:00
leo
ced1737bdc
fix: typo in DataTimeFormat 2024-12-30 20:29:50 +08:00
leo
82fc261743
feature: shows the git configured commit template in Template/Histories popup (#846) 2024-12-30 19:40:58 +08:00
leo
8d12227227
ux: show date time format string 2024-12-30 17:47:55 +08:00
leo
7d0fa3b86d
Revert "feature: ignore remote.{REMOTE}.mirror settings (#844)"
This reverts commit 093176d10b.
2024-12-30 17:34:58 +08:00
github-actions[bot]
418897c5de doc: Update translation status and missing keys 2024-12-30 09:20:17 +00:00
leo
c058b4744b
feature: allows to change DateTime format (#755) 2024-12-30 17:19:55 +08:00
leo
dc649e6142
refactor: rewrite the portable mode (#851) 2024-12-30 15:12:23 +08:00
leo
093176d10b
feature: ignore remote.{REMOTE}.mirror settings (#844)
(cherry picked from commit 9164f1b7340f68e00fea99bf9bac67734062f930)
2024-12-30 14:54:04 +08:00
21 changed files with 208 additions and 77 deletions

View file

@ -47,7 +47,7 @@
## Translation Status ## Translation Status
[![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-100.00%25-brightgreen)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-100.00%25-brightgreen)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-95.00%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-95.56%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-96.81%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-100.00%25-brightgreen)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md) [![en_US](https://img.shields.io/badge/en__US-100%25-brightgreen)](TRANSLATION.md) [![de__DE](https://img.shields.io/badge/de__DE-99.86%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-99.86%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-94.87%25-yellow)](TRANSLATION.md) [![it__IT](https://img.shields.io/badge/it__IT-95.42%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-96.67%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-99.86%25-yellow)](TRANSLATION.md) [![zh__CN](https://img.shields.io/badge/zh__CN-100.00%25-brightgreen)](TRANSLATION.md) [![zh__TW](https://img.shields.io/badge/zh__TW-100.00%25-brightgreen)](TRANSLATION.md)
## How to Use ## How to Use
@ -64,7 +64,8 @@ This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationD
| macOS | `${HOME}/Library/Application Support/SourceGit` | | macOS | `${HOME}/Library/Application Support/SourceGit` |
> [!TIP] > [!TIP]
> You can open this data storage directory from the main menu. > * You can open this data storage directory from the main menu `Open Data Storage Directory`.
> * You can create a `data` folder next to the `SourceGit` executable to force this app to store data (user settings, downloaded avatars and crash logs) into it (Portable-Mode). Only works on Windows.
For **Windows** users: For **Windows** users:
@ -81,7 +82,6 @@ For **Windows** users:
scoop install sourcegit scoop install sourcegit
``` ```
* Pre-built binaries can be found in [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest) * Pre-built binaries can be found in [Releases](https://github.com/sourcegit-scm/sourcegit/releases/latest)
* You can run `dotnet publish -c Release -r win-x64 -p:EnablePortable=true -o $YOUR_PUBLISH_DIR .\src\SourceGit.csproj` to build a portable version.
For **macOS** users: For **macOS** users:

View file

@ -1,24 +1,24 @@
### de_DE.axaml: 100.00% ### de_DE.axaml: 99.86%
<details> <details>
<summary>Missing Keys</summary> <summary>Missing Keys</summary>
- Text.Preference.General.DateFormat
</details> </details>
### es_ES.axaml: 100.00% ### es_ES.axaml: 99.86%
<details> <details>
<summary>Missing Keys</summary> <summary>Missing Keys</summary>
- Text.Preference.General.DateFormat
</details> </details>
### fr_FR.axaml: 95.00% ### fr_FR.axaml: 94.87%
<details> <details>
@ -47,6 +47,7 @@
- Text.Preference.Appearance.FontSize - Text.Preference.Appearance.FontSize
- Text.Preference.Appearance.FontSize.Default - Text.Preference.Appearance.FontSize.Default
- Text.Preference.Appearance.FontSize.Editor - Text.Preference.Appearance.FontSize.Editor
- Text.Preference.General.DateFormat
- Text.Preference.General.ShowChildren - Text.Preference.General.ShowChildren
- Text.Repository.CustomActions - Text.Repository.CustomActions
- Text.Repository.FilterCommits - Text.Repository.FilterCommits
@ -63,7 +64,7 @@
</details> </details>
### it_IT.axaml: 95.56% ### it_IT.axaml: 95.42%
<details> <details>
@ -89,6 +90,7 @@
- Text.MergeMultiple.CommitChanges - Text.MergeMultiple.CommitChanges
- Text.MergeMultiple.Strategy - Text.MergeMultiple.Strategy
- Text.MergeMultiple.Targets - Text.MergeMultiple.Targets
- Text.Preference.General.DateFormat
- Text.Preference.General.ShowChildren - Text.Preference.General.ShowChildren
- Text.Repository.FilterCommits - Text.Repository.FilterCommits
- Text.Repository.FilterCommits.Default - Text.Repository.FilterCommits.Default
@ -104,7 +106,7 @@
</details> </details>
### pt_BR.axaml: 96.81% ### pt_BR.axaml: 96.67%
<details> <details>
@ -128,6 +130,7 @@
- Text.MergeMultiple.CommitChanges - Text.MergeMultiple.CommitChanges
- Text.MergeMultiple.Strategy - Text.MergeMultiple.Strategy
- Text.MergeMultiple.Targets - Text.MergeMultiple.Targets
- Text.Preference.General.DateFormat
- Text.Preference.General.ShowChildren - Text.Preference.General.ShowChildren
- Text.Repository.FilterCommits - Text.Repository.FilterCommits
- Text.Repository.Skip - Text.Repository.Skip
@ -136,13 +139,13 @@
</details> </details>
### ru_RU.axaml: 100.00% ### ru_RU.axaml: 99.86%
<details> <details>
<summary>Missing Keys</summary> <summary>Missing Keys</summary>
- Text.Preference.General.DateFormat
</details> </details>

View file

@ -65,7 +65,7 @@ namespace SourceGit.Commands
var commit = match.Groups[1].Value; var commit = match.Groups[1].Value;
var author = match.Groups[2].Value; var author = match.Groups[2].Value;
var timestamp = int.Parse(match.Groups[3].Value); var timestamp = int.Parse(match.Groups[3].Value);
var when = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime().ToString("yyyy/MM/dd"); var when = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime().ToString(_dateFormat);
var info = new Models.BlameLineInfo() var info = new Models.BlameLineInfo()
{ {
@ -87,6 +87,7 @@ namespace SourceGit.Commands
private readonly Models.BlameData _result = new Models.BlameData(); private readonly Models.BlameData _result = new Models.BlameData();
private readonly StringBuilder _content = new StringBuilder(); private readonly StringBuilder _content = new StringBuilder();
private readonly string _dateFormat = Models.DateTimeFormat.Actived.DateOnly;
private string _lastSHA = string.Empty; private string _lastSHA = string.Empty;
private bool _needUnifyCommitSHA = false; private bool _needUnifyCommitSHA = false;
private int _minSHALen = 64; private int _minSHALen = 64;

View file

@ -53,18 +53,8 @@ namespace SourceGit.Commands
proc.BeginOutputReadLine(); proc.BeginOutputReadLine();
proc.BeginErrorReadLine(); proc.BeginErrorReadLine();
proc.WaitForExit(); proc.WaitForExit();
}
catch (Exception e)
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, e.Message);
});
}
var exitCode = proc.ExitCode; var exitCode = proc.ExitCode;
proc.Close();
if (exitCode != 0) if (exitCode != 0)
{ {
var errMsg = builder.ToString(); var errMsg = builder.ToString();
@ -74,5 +64,15 @@ namespace SourceGit.Commands
}); });
} }
} }
catch (Exception e)
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, e.Message);
});
}
proc.Close();
}
} }
} }

View file

@ -31,9 +31,9 @@ namespace SourceGit.Models
public List<Decorator> Decorators { get; set; } = new List<Decorator>(); public List<Decorator> Decorators { get; set; } = new List<Decorator>();
public bool HasDecorators => Decorators.Count > 0; public bool HasDecorators => Decorators.Count > 0;
public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss"); public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss"); public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString("yyyy/MM/dd"); public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly);
public bool IsMerged { get; set; } = false; public bool IsMerged { get; set; } = false;
public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime; public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime;

View file

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
namespace SourceGit.Models
{
public class DateTimeFormat
{
public string DateOnly { get; set; }
public string DateTime { get; set; }
public string Example
{
get => _example.ToString(DateTime);
}
public DateTimeFormat(string dateOnly, string dateTime)
{
DateOnly = dateOnly;
DateTime = dateTime;
}
public static int ActiveIndex
{
get;
set;
} = 0;
public static DateTimeFormat Actived
{
get => Supported[ActiveIndex];
}
public static readonly List<DateTimeFormat> Supported = new List<DateTimeFormat>
{
new DateTimeFormat("yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss"),
new DateTimeFormat("yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss"),
new DateTimeFormat("yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss"),
new DateTimeFormat("MM/dd/yyyy", "MM/dd/yyyy HH:mm:ss"),
new DateTimeFormat("MM.dd.yyyy", "MM.dd.yyyy HH:mm:ss"),
new DateTimeFormat("MM-dd-yyyy", "MM-dd-yyyy HH:mm:ss"),
new DateTimeFormat("dd/MM/yyyy", "dd/MM/yyyy HH:mm:ss"),
new DateTimeFormat("dd.MM.yyyy", "dd.MM.yyyy HH:mm:ss"),
new DateTimeFormat("dd-MM-yyyy", "dd-MM-yyyy HH:mm:ss"),
new DateTimeFormat("MMM d yyyy", "MMM d yyyy HH:mm:ss"),
new DateTimeFormat("d MMM yyyy", "d MMM yyyy HH:mm:ss"),
};
private static readonly DateTime _example = new DateTime(2025, 1, 31, 8, 0, 0, DateTimeKind.Local);
}
}

View file

@ -9,6 +9,6 @@ namespace SourceGit.Models
public ulong Time { get; set; } = 0; public ulong Time { get; set; } = 0;
public string Message { get; set; } = ""; public string Message { get; set; } = "";
public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss"); public string TimeStr => DateTime.UnixEpoch.AddSeconds(Time).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime);
} }
} }

View file

@ -25,7 +25,12 @@ namespace SourceGit.Native
public string FindGitExecutable() public string FindGitExecutable()
{ {
return File.Exists("/usr/bin/git") ? "/usr/bin/git" : string.Empty; var gitPathVariants = new List<string>() {
"/usr/bin/git", "/usr/local/bin/git", "/opt/homebrew/bin/git", "/opt/homebrew/opt/git/bin/git"
};
foreach (var path in gitPathVariants)
if (File.Exists(path)) return path;
return string.Empty;
} }
public string FindTerminal(Models.ShellOrTerminal shell) public string FindTerminal(Models.ShellOrTerminal shell)

View file

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
#if ENABLE_PORTABLE
using System.Diagnostics; using System.Diagnostics;
#endif
using System.IO; using System.IO;
using Avalonia; using Avalonia;
@ -58,16 +56,17 @@ namespace SourceGit.Native
public static void SetupDataDir() public static void SetupDataDir()
{ {
#if ENABLE_PORTABLE
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
var execFile = Process.GetCurrentProcess().MainModule!.FileName; var execFile = Process.GetCurrentProcess().MainModule!.FileName;
DataDir = Path.Combine(Path.GetDirectoryName(execFile), "data"); var portableDir = Path.Combine(Path.GetDirectoryName(execFile), "data");
if (!Directory.Exists(DataDir)) if (Directory.Exists(portableDir))
Directory.CreateDirectory(DataDir); {
DataDir = portableDir;
return; return;
} }
#endif }
var osAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); var osAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (string.IsNullOrEmpty(osAppDataDir)) if (string.IsNullOrEmpty(osAppDataDir))
DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".sourcegit"); DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".sourcegit");

View file

@ -465,6 +465,7 @@
<x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">Tool</x:String> <x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">Tool</x:String>
<x:String x:Key="Text.Preference.General" xml:space="preserve">GENERAL</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.Check4UpdatesOnStartup" xml:space="preserve">Check for updates on startup</x:String>
<x:String x:Key="Text.Preference.General.DateFormat" xml:space="preserve">Date Format</x:String>
<x:String x:Key="Text.Preference.General.Locale" xml:space="preserve">Language</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.MaxHistoryCommits" xml:space="preserve">History Commits</x:String>
<x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">Show author time instead of commit time in graph</x:String> <x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">Show author time instead of commit time in graph</x:String>

View file

@ -469,6 +469,7 @@
<x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">工具</x:String> <x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">工具</x:String>
<x:String x:Key="Text.Preference.General" 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.Check4UpdatesOnStartup" xml:space="preserve">启动时检测软件更新</x:String>
<x:String x:Key="Text.Preference.General.DateFormat" 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.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.MaxHistoryCommits" xml:space="preserve">最大历史提交数</x:String>
<x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">在提交路线图中显示修改时间而非提交时间</x:String> <x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">在提交路线图中显示修改时间而非提交时间</x:String>

View file

@ -468,6 +468,7 @@
<x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">工具</x:String> <x:String x:Key="Text.Preference.DiffMerge.Type" xml:space="preserve">工具</x:String>
<x:String x:Key="Text.Preference.General" 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.Check4UpdatesOnStartup" xml:space="preserve">啟動時檢查軟體更新</x:String>
<x:String x:Key="Text.Preference.General.DateFormat" 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.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.MaxHistoryCommits" xml:space="preserve">最大歷史提交數</x:String>
<x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">在提交路線圖中顯示修改時間而非提交時間</x:String> <x:String x:Key="Text.Preference.General.ShowAuthorTime" xml:space="preserve">在提交路線圖中顯示修改時間而非提交時間</x:String>

View file

@ -30,10 +30,6 @@
<DefineConstants>$(DefineConstants);DISABLE_UPDATE_DETECTION</DefineConstants> <DefineConstants>$(DefineConstants);DISABLE_UPDATE_DETECTION</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(EnablePortable)' == 'true'">
<DefineConstants>$(DefineConstants);ENABLE_PORTABLE</DefineConstants>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<AvaloniaResource Include="App.ico" /> <AvaloniaResource Include="App.ico" />
<AvaloniaResource Include="Resources/Fonts/*" /> <AvaloniaResource Include="Resources/Fonts/*" />

View file

@ -23,7 +23,7 @@ namespace SourceGit.ViewModels
{ {
_repo = repo; _repo = repo;
_revision = branch.Head; _revision = branch.Head;
_saveFile = $"archive-{Path.GetFileNameWithoutExtension(branch.Name)}.zip"; _saveFile = $"archive-{Path.GetFileName(branch.Name)}.zip";
BasedOn = branch; BasedOn = branch;
View = new Views.Archive() { DataContext = this }; View = new Views.Archive() { DataContext = this };
} }
@ -41,7 +41,7 @@ namespace SourceGit.ViewModels
{ {
_repo = repo; _repo = repo;
_revision = tag.SHA; _revision = tag.SHA;
_saveFile = $"archive-{tag.Name}.zip"; _saveFile = $"archive-{Path.GetFileName(tag.Name)}.zip";
BasedOn = tag; BasedOn = tag;
View = new Views.Archive() { DataContext = this }; View = new Views.Archive() { DataContext = this };
} }

View file

@ -129,6 +129,21 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _subjectGuideLength, value); set => SetProperty(ref _subjectGuideLength, value);
} }
public int DateTimeFormat
{
get => Models.DateTimeFormat.ActiveIndex;
set
{
if (value != Models.DateTimeFormat.ActiveIndex &&
value >= 0 &&
value < Models.DateTimeFormat.Supported.Count)
{
Models.DateTimeFormat.ActiveIndex = value;
OnPropertyChanged();
}
}
}
public bool UseFixedTabWidth public bool UseFixedTabWidth
{ {
get => _useFixedTabWidth; get => _useFixedTabWidth;

View file

@ -1351,8 +1351,9 @@ namespace SourceGit.ViewModels
{ {
var menu = new ContextMenu(); var menu = new ContextMenu();
var gitTemplate = new Commands.Config(_repo.FullPath).Get("commit.template");
var templateCount = _repo.Settings.CommitTemplates.Count; var templateCount = _repo.Settings.CommitTemplates.Count;
if (templateCount == 0) if (templateCount == 0 && string.IsNullOrEmpty(gitTemplate))
{ {
menu.Items.Add(new MenuItem() menu.Items.Add(new MenuItem()
{ {
@ -1376,6 +1377,29 @@ namespace SourceGit.ViewModels
}; };
menu.Items.Add(item); menu.Items.Add(item);
} }
if (!string.IsNullOrEmpty(gitTemplate))
{
var friendlyName = gitTemplate;
if (!OperatingSystem.IsWindows())
{
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var prefixLen = home.EndsWith('/') ? home.Length - 1 : home.Length;
if (gitTemplate.StartsWith(home, StringComparison.Ordinal))
friendlyName = "~" + gitTemplate.Substring(prefixLen);
}
var gitTemplateItem = new MenuItem();
gitTemplateItem.Header = new Views.NameHighlightedTextBlock("WorkingCopy.UseCommitTemplate", friendlyName);
gitTemplateItem.Icon = App.CreateMenuIcon("Icons.Code");
gitTemplateItem.Click += (_, e) =>
{
if (File.Exists(gitTemplate))
CommitMessage = File.ReadAllText(gitTemplate);
e.Handled = true;
};
menu.Items.Add(gitTemplateItem);
}
} }
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });

View file

@ -37,6 +37,7 @@ namespace SourceGit.Views
{ {
var typeface = view.CreateTypeface(); var typeface = view.CreateTypeface();
var underlinePen = new Pen(Brushes.DarkOrange); var underlinePen = new Pen(Brushes.DarkOrange);
var width = Bounds.Width;
foreach (var line in view.VisualLines) foreach (var line in view.VisualLines)
{ {
@ -64,16 +65,6 @@ namespace SourceGit.Views
context.DrawLine(underlinePen, new Point(x, y + shaLink.Baseline + 2), new Point(x + shaLink.Width, y + shaLink.Baseline + 2)); context.DrawLine(underlinePen, new Point(x, y + shaLink.Baseline + 2), new Point(x + shaLink.Width, y + shaLink.Baseline + 2));
x += shaLink.Width + 8; x += shaLink.Width + 8;
var time = new FormattedText(
info.Time,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
typeface,
_editor.FontSize,
_editor.Foreground);
context.DrawText(time, new Point(x, y));
x += time.Width + 8;
var author = new FormattedText( var author = new FormattedText(
info.Author, info.Author,
CultureInfo.CurrentCulture, CultureInfo.CurrentCulture,
@ -82,6 +73,15 @@ namespace SourceGit.Views
_editor.FontSize, _editor.FontSize,
_editor.Foreground); _editor.Foreground);
context.DrawText(author, new Point(x, y)); context.DrawText(author, new Point(x, y));
var time = new FormattedText(
info.Time,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
typeface,
_editor.FontSize,
_editor.Foreground);
context.DrawText(time, new Point(width - time.Width, y));
} }
} }
} }
@ -116,15 +116,6 @@ namespace SourceGit.Views
Brushes.DarkOrange); Brushes.DarkOrange);
x += shaLink.Width + 8; x += shaLink.Width + 8;
var time = new FormattedText(
info.Time,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
typeface,
_editor.FontSize,
_editor.Foreground);
x += time.Width + 8;
var author = new FormattedText( var author = new FormattedText(
info.Author, info.Author,
CultureInfo.CurrentCulture, CultureInfo.CurrentCulture,
@ -132,7 +123,16 @@ namespace SourceGit.Views
typeface, typeface,
_editor.FontSize, _editor.FontSize,
_editor.Foreground); _editor.Foreground);
x += author.Width; x += author.Width + 8;
var time = new FormattedText(
info.Time,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
typeface,
_editor.FontSize,
_editor.Foreground);
x += time.Width;
if (maxWidth < x) if (maxWidth < x)
maxWidth = x; maxWidth = x;

View file

@ -78,7 +78,7 @@
<DataTemplate DataType="m:Commit"> <DataTemplate DataType="m:Commit">
<Border BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1" Padding="4"> <Border BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="0,0,0,1" Padding="4">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto"> <Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,96">
<v:Avatar Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" IsHitTestVisible="False" User="{Binding Author}"/> <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" TextTrimming="CharacterEllipsis"/> <TextBlock Grid.Column="1" Classes="primary" Text="{Binding Author.Name}" Margin="8,0,0,0" TextTrimming="CharacterEllipsis"/>
<TextBlock Grid.Column="2" <TextBlock Grid.Column="2"
@ -90,7 +90,7 @@
TextDecorations="Underline" TextDecorations="Underline"
Margin="8,0,0,0" Margin="8,0,0,0"
PointerPressed="OnPressCommitSHA"/> PointerPressed="OnPressCommitSHA"/>
<TextBlock Grid.Column="3" Classes="primary" Text="{Binding AuthorTimeShortStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/> <TextBlock Grid.Column="3" Classes="primary" Text="{Binding AuthorTimeShortStr}" Foreground="{DynamicResource Brush.FG2}" HorizontalAlignment="Right"/>
</Grid> </Grid>
<TextBlock Grid.Row="1" Classes="primary" Text="{Binding Subject}" VerticalAlignment="Bottom"/> <TextBlock Grid.Row="1" Classes="primary" Text="{Binding Subject}" VerticalAlignment="Bottom"/>

View file

@ -191,7 +191,8 @@
FontWeight="{Binding FontWeight}" FontWeight="{Binding FontWeight}"
Opacity="{Binding Opacity}" Opacity="{Binding Opacity}"
UseAuthorTime="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowAuthorTimeInGraph, Mode=OneWay}" UseAuthorTime="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowAuthorTimeInGraph, Mode=OneWay}"
ShowAsDateTime="{Binding Source={x:Static vm:Preference.Instance}, Path=!DisplayTimeAsPeriodInHistories}"/> ShowAsDateTime="{Binding Source={x:Static vm:Preference.Instance}, Path=!DisplayTimeAsPeriodInHistories}"
DateTimeFormat="{Binding Source={x:Static vm:Preference.Instance}, Path=DateTimeFormat}"/>
</Border> </Border>
</Grid> </Grid>
</DataTemplate> </DataTemplate>

View file

@ -343,6 +343,15 @@ namespace SourceGit.Views
set => SetValue(ShowAsDateTimeProperty, value); set => SetValue(ShowAsDateTimeProperty, value);
} }
public static readonly StyledProperty<int> DateTimeFormatProperty =
AvaloniaProperty.Register<CommitTimeTextBlock, int>(nameof(DateTimeFormat), 0);
public int DateTimeFormat
{
get => GetValue(DateTimeFormatProperty);
set => SetValue(DateTimeFormatProperty, value);
}
public static readonly StyledProperty<bool> UseAuthorTimeProperty = public static readonly StyledProperty<bool> UseAuthorTimeProperty =
AvaloniaProperty.Register<CommitTimeTextBlock, bool>(nameof(UseAuthorTime), true); AvaloniaProperty.Register<CommitTimeTextBlock, bool>(nameof(UseAuthorTime), true);
@ -371,6 +380,11 @@ namespace SourceGit.Views
else else
StartTimer(); StartTimer();
} }
else if (change.Property == DateTimeFormatProperty)
{
if (ShowAsDateTime)
SetCurrentValue(TextProperty, GetDisplayText());
}
} }
protected override void OnLoaded(RoutedEventArgs e) protected override void OnLoaded(RoutedEventArgs e)
@ -426,10 +440,10 @@ namespace SourceGit.Views
if (commit == null) if (commit == null)
return string.Empty; return string.Empty;
var timestamp = UseAuthorTime ? commit.AuthorTime : commit.CommitterTime;
if (ShowAsDateTime) if (ShowAsDateTime)
return DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss"); return UseAuthorTime ? commit.AuthorTimeStr : commit.CommitterTimeStr;
var timestamp = UseAuthorTime ? commit.AuthorTime : commit.CommitterTime;
var now = DateTime.Now; var now = DateTime.Now;
var localTime = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime(); var localTime = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime();
var span = now - localTime; var span = now - localTime;

View file

@ -46,7 +46,7 @@
<TabItem.Header> <TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/> <TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/>
</TabItem.Header> </TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*"> <Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.Locale}" Text="{DynamicResource Text.Preference.General.Locale}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
@ -60,10 +60,30 @@
SelectedItem="{Binding Locale, Mode=TwoWay, Converter={x:Static c:StringConverters.ToLocale}}"/> SelectedItem="{Binding Locale, Mode=TwoWay, Converter={x:Static c:StringConverters.ToLocale}}"/>
<TextBlock Grid.Row="1" Grid.Column="0" <TextBlock Grid.Row="1" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.DateFormat}"
HorizontalAlignment="Right"
Margin="0,0,16,0"/>
<ComboBox Grid.Row="1" Grid.Column="1"
MinHeight="28"
Padding="8,0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Source={x:Static m:DateTimeFormat.Supported}}"
SelectedIndex="{Binding DateTimeFormat, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="{x:Type m:DateTimeFormat}">
<Grid ColumnDefinitions="*,8,*">
<TextBlock Grid.Column="0" FontFamily="{DynamicResource Fonts.Monospace}" Text="{Binding Example}"/>
<TextBlock Grid.Column="2" FontFamily="{DynamicResource Fonts.Monospace}" Text="{Binding DateTime}" Foreground="{DynamicResource Brush.FG2}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Preference.Git.DefaultCloneDir}" Text="{DynamicResource Text.Preference.Git.DefaultCloneDir}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Margin="0,0,16,0"/> Margin="0,0,16,0"/>
<TextBox Grid.Row="1" Grid.Column="1" <TextBox Grid.Row="2" Grid.Column="1"
Height="28" Height="28"
CornerRadius="3" CornerRadius="3"
Text="{Binding GitDefaultCloneDir, Mode=TwoWay}"> Text="{Binding GitDefaultCloneDir, Mode=TwoWay}">
@ -74,11 +94,11 @@
</TextBox.InnerRightContent> </TextBox.InnerRightContent>
</TextBox> </TextBox>
<TextBlock Grid.Row="2" Grid.Column="0" <TextBlock Grid.Row="3" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.SubjectGuideLength}" Text="{DynamicResource Text.Preference.General.SubjectGuideLength}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Margin="0,0,16,0"/> Margin="0,0,16,0"/>
<NumericUpDown Grid.Row="2" Grid.Column="1" <NumericUpDown Grid.Row="3" Grid.Column="1"
Minimum="50" Maximum="1000" Increment="1" Minimum="50" Maximum="1000" Increment="1"
Height="28" Height="28"
Padding="4" Padding="4"
@ -87,11 +107,11 @@
CornerRadius="3" CornerRadius="3"
Value="{Binding SubjectGuideLength, Mode=TwoWay}"/> Value="{Binding SubjectGuideLength, Mode=TwoWay}"/>
<TextBlock Grid.Row="3" Grid.Column="0" <TextBlock Grid.Row="4" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.MaxHistoryCommits}" Text="{DynamicResource Text.Preference.General.MaxHistoryCommits}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
Margin="0,0,16,0"/> Margin="0,0,16,0"/>
<Grid Grid.Row="3" Grid.Column="1" ColumnDefinitions="*,64"> <Grid Grid.Row="4" Grid.Column="1" ColumnDefinitions="*,64">
<Slider Grid.Column="0" <Slider Grid.Column="0"
Minimum="5000" Maximum="100000" Minimum="5000" Maximum="100000"
TickPlacement="BottomRight" TickFrequency="5000" TickPlacement="BottomRight" TickFrequency="5000"
@ -106,17 +126,17 @@
Text="{Binding MaxHistoryCommits}"/> Text="{Binding MaxHistoryCommits}"/>
</Grid> </Grid>
<CheckBox Grid.Row="4" Grid.Column="1" <CheckBox Grid.Row="5" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Preference.General.ShowAuthorTime}" Content="{DynamicResource Text.Preference.General.ShowAuthorTime}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowAuthorTimeInGraph, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowAuthorTimeInGraph, Mode=TwoWay}"/>
<CheckBox Grid.Row="5" Grid.Column="1" <CheckBox Grid.Row="6" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Preference.General.ShowChildren}" Content="{DynamicResource Text.Preference.General.ShowChildren}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowChildren, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=ShowChildren, Mode=TwoWay}"/>
<CheckBox Grid.Row="6" Grid.Column="1" <CheckBox Grid.Row="7" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}" Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}"
IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}" IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}"