diff --git a/README.md b/README.md index 7e4db671..10e803d6 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,10 @@ ## 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-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) + +> [!NOTE] +> You can find the missing keys in [TRANSLATION.md](TRANSLATION.md) ## How to Use @@ -64,7 +67,8 @@ This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationD | macOS | `${HOME}/Library/Application Support/SourceGit` | > [!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: @@ -81,7 +85,6 @@ For **Windows** users: scoop install sourcegit ``` * 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: @@ -190,6 +193,15 @@ This app supports open repository in external tools listed in the table below. Everyone is welcome to submit a PR. Please make sure your PR is based on the latest `develop` branch and the target branch of PR is `develop`. +In short, here are the commands to get started once [.NET tools are installed](https://dotnet.microsoft.com/en-us/download): + +```sh +dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org +dotnet restore +dotnet build +dotnet run --project src/SourceGit.csproj +``` + Thanks to all the people who contribute. [![Contributors](https://contrib.rocks/image?repo=sourcegit-scm/sourcegit&columns=20)](https://github.com/sourcegit-scm/sourcegit/graphs/contributors) diff --git a/TRANSLATION.md b/TRANSLATION.md index 69962320..30b181ca 100644 --- a/TRANSLATION.md +++ b/TRANSLATION.md @@ -1,24 +1,24 @@ -### de_DE.axaml: 100.00% +### de_DE.axaml: 99.86%
Missing Keys - +- Text.Preference.General.DateFormat
-### es_ES.axaml: 100.00% +### es_ES.axaml: 99.86%
Missing Keys - +- Text.Preference.General.DateFormat
-### fr_FR.axaml: 95.00% +### fr_FR.axaml: 94.87%
@@ -47,6 +47,7 @@ - Text.Preference.Appearance.FontSize - Text.Preference.Appearance.FontSize.Default - Text.Preference.Appearance.FontSize.Editor +- Text.Preference.General.DateFormat - Text.Preference.General.ShowChildren - Text.Repository.CustomActions - Text.Repository.FilterCommits @@ -63,7 +64,7 @@
-### it_IT.axaml: 95.56% +### it_IT.axaml: 95.42%
@@ -89,6 +90,7 @@ - Text.MergeMultiple.CommitChanges - Text.MergeMultiple.Strategy - Text.MergeMultiple.Targets +- Text.Preference.General.DateFormat - Text.Preference.General.ShowChildren - Text.Repository.FilterCommits - Text.Repository.FilterCommits.Default @@ -104,7 +106,7 @@
-### pt_BR.axaml: 96.81% +### pt_BR.axaml: 96.67%
@@ -128,6 +130,7 @@ - Text.MergeMultiple.CommitChanges - Text.MergeMultiple.Strategy - Text.MergeMultiple.Targets +- Text.Preference.General.DateFormat - Text.Preference.General.ShowChildren - Text.Repository.FilterCommits - Text.Repository.Skip diff --git a/VERSION b/VERSION index b977bf8c..d612525a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.45 \ No newline at end of file +2025.01 \ No newline at end of file diff --git a/src/Commands/Blame.cs b/src/Commands/Blame.cs index de221b07..291249be 100644 --- a/src/Commands/Blame.cs +++ b/src/Commands/Blame.cs @@ -65,7 +65,7 @@ namespace SourceGit.Commands var commit = match.Groups[1].Value; var author = match.Groups[2].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() { @@ -87,6 +87,7 @@ namespace SourceGit.Commands private readonly Models.BlameData _result = new Models.BlameData(); private readonly StringBuilder _content = new StringBuilder(); + private readonly string _dateFormat = Models.DateTimeFormat.Actived.DateOnly; private string _lastSHA = string.Empty; private bool _needUnifyCommitSHA = false; private int _minSHALen = 64; diff --git a/src/Commands/ExecuteCustomAction.cs b/src/Commands/ExecuteCustomAction.cs index 4981b2f9..a10f5387 100644 --- a/src/Commands/ExecuteCustomAction.cs +++ b/src/Commands/ExecuteCustomAction.cs @@ -53,6 +53,16 @@ namespace SourceGit.Commands proc.BeginOutputReadLine(); proc.BeginErrorReadLine(); proc.WaitForExit(); + + var exitCode = proc.ExitCode; + if (exitCode != 0) + { + var errMsg = builder.ToString(); + Dispatcher.UIThread.Invoke(() => + { + App.RaiseException(repo, errMsg); + }); + } } catch (Exception e) { @@ -62,17 +72,7 @@ namespace SourceGit.Commands }); } - var exitCode = proc.ExitCode; proc.Close(); - - if (exitCode != 0) - { - var errMsg = builder.ToString(); - Dispatcher.UIThread.Invoke(() => - { - App.RaiseException(repo, errMsg); - }); - } } } } diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index 534cf5bb..9bc7f0c3 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -31,9 +31,9 @@ namespace SourceGit.Models public List Decorators { get; set; } = new List(); public bool HasDecorators => Decorators.Count > 0; - public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss"); - public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss"); - public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString("yyyy/MM/dd"); + public string AuthorTimeStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); + public string CommitterTimeStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateTime); + public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Actived.DateOnly); public bool IsMerged { get; set; } = false; public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime; diff --git a/src/Models/DateTimeFormat.cs b/src/Models/DateTimeFormat.cs new file mode 100644 index 00000000..4e71a74f --- /dev/null +++ b/src/Models/DateTimeFormat.cs @@ -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 Supported = new List + { + 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); + } +} diff --git a/src/Models/Stash.cs b/src/Models/Stash.cs index 06da763a..3d395a84 100644 --- a/src/Models/Stash.cs +++ b/src/Models/Stash.cs @@ -9,6 +9,6 @@ namespace SourceGit.Models public ulong Time { get; set; } = 0; 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); } } diff --git a/src/Native/MacOS.cs b/src/Native/MacOS.cs index 62ae8c89..5721fe87 100644 --- a/src/Native/MacOS.cs +++ b/src/Native/MacOS.cs @@ -25,7 +25,12 @@ namespace SourceGit.Native public string FindGitExecutable() { - return File.Exists("/usr/bin/git") ? "/usr/bin/git" : string.Empty; + var gitPathVariants = new List() { + "/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) diff --git a/src/Native/OS.cs b/src/Native/OS.cs index ca56cdac..c8c9e92d 100644 --- a/src/Native/OS.cs +++ b/src/Native/OS.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -#if ENABLE_PORTABLE using System.Diagnostics; -#endif using System.IO; using Avalonia; @@ -58,16 +56,17 @@ namespace SourceGit.Native public static void SetupDataDir() { -#if ENABLE_PORTABLE if (OperatingSystem.IsWindows()) { var execFile = Process.GetCurrentProcess().MainModule!.FileName; - DataDir = Path.Combine(Path.GetDirectoryName(execFile), "data"); - if (!Directory.Exists(DataDir)) - Directory.CreateDirectory(DataDir); - return; + var portableDir = Path.Combine(Path.GetDirectoryName(execFile), "data"); + if (Directory.Exists(portableDir)) + { + DataDir = portableDir; + return; + } } -#endif + var osAppDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); if (string.IsNullOrEmpty(osAppDataDir)) DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".sourcegit"); diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index f2165f3f..f47454aa 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -465,6 +465,7 @@ Tool GENERAL Check for updates on startup + Date Format Language History Commits Show author time instead of commit time in graph diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 20237bb9..32c043d3 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -12,7 +12,7 @@ • Le code source est disponible sur Client Git Open Source et Gratuit Ajouter un Worktree - What to Checkout: + Que récupérer : Créer une nouvelle branche Branche existante Emplacement : @@ -49,7 +49,7 @@ FICHIER BINAIRE NON SUPPORTÉ !!! Blâme LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!! - Checkout ${0}$... + Récupérer ${0}$... Comparer avec la branche Comparer avec HEAD Comparer avec le worktree @@ -78,10 +78,10 @@ Afficher comme liste de dossiers/fichiers Afficher comme liste de chemins Afficher comme arborescence - Checkout Branch - Checkout ce commit + Récupérer la branche + Récupérer ce commit Commit : - Avertissement: un checkout vers un commit aboutiera vers un HEAD détaché + Avertissement: une récupération vers un commit aboutiera vers un HEAD détaché Branche : Changements locaux : Annuler @@ -103,7 +103,7 @@ URL du dépôt : FERMER Éditeur - Changer de commit + Récupérer ce commit Cherry-Pick ce commit Comparer avec HEAD Comparer avec le worktree @@ -191,7 +191,7 @@ Copier le chemin Créer une branche... Basé sur : - Passer à la branche créée + Récupérer la branche créée Changements locaux : Rejeter Ne rien faire @@ -266,7 +266,7 @@ Éditer le dépôt sélectionné Lancer action personnalisée Nom de l'action : - Fast-Forward (sans checkout) + Fast-Forward (sans récupération) Fetch Fetch toutes les branches distantes Fetch sans les tags @@ -334,9 +334,9 @@ Lancer `git lfs prune` pour supprimer les anciens fichier LFS du stockage local Pull Pull les objets LFS - Lancer `git lfs pull` pour télécharger tous les fichier Git LFS de la référence actuelle & checkout - Push - Push les objets LFS + Lancer `git lfs pull` pour télécharger tous les fichier Git LFS de la référence actuelle & récupérer + Pousser + Pousser les objets LFS Transférer les fichiers volumineux en file d'attente vers le point de terminaison Git LFS Dépôt : Suivre les fichiers appelés '{0}' @@ -381,15 +381,15 @@ Trouver la prochaine correspondance Trouver la correspondance précédente Ouvrir le panneau de recherche - Stage + Indexer Retirer de l'index Rejeter Initialiser le repository Chemin : Cherry-Pick en cours. - Merge request in progress. - Rebase in progress. - Revert in progress. + Merge request en cours. + Rebase en cours. + Annulation en cours. Rebase interactif Branche cible : Sur : @@ -412,9 +412,9 @@ Fermer l'onglet Fermer les autres onglets Fermer les onglets à droite - Copy Repository Path + Copier le chemin vers le dépôt Dépôts - Paste + Coller A l'instant il y a {0} minutes il y a {0} heures @@ -490,17 +490,17 @@ Dépôt distant : Pull (Fetch & Merge) Utiliser rebase au lieu de merge - Push + Pousser Assurez-vous que les submodules ont été poussés - Force push + Poussage forcé Branche locale : Dépôt distant : Pousser les changements vers le dépôt distant Branche distante : Définir comme branche de suivi - Push tous les tags - Push Tag To Remote - Push tous les dépôts distants + Pousser tous les tags + Pousser les tags vers le dépôt distant + Pousser tous les dépôts distants Dépôt distant : Tag : Quitter @@ -571,9 +571,9 @@ Déplacer vers : Branche actuelle : Ouvrir dans l'explorateur de fichier - Revert le Commit + Annuler le Commit Commit : - Commit les changements du revert + Commit les changements de l'annulation Reformuler le message de commit Utiliser 'Maj+Entrée' pour insérer une nouvelle ligne. 'Entrée' est la touche pour valider En exécution. Veuillez patienter... @@ -591,16 +591,16 @@ Copier le SHA Squash Commits Dans : - SSH Private Key: - Private SSH key store path + Clé privée SSH : + Chemin du magasin de clés privées SSH START Stash - Include untracked files - Garder les fichiers staged + Inclure les fichiers non-suivis + Garder les fichiers indexés Message : Optionnel. Nom de ce stash - Seulement les changements staged - Les modifications staged et unstaged des fichiers sélectionnés seront stockées!!! + Seulement les changements indexés + Les modifications indexées et non-indexées des fichiers sélectionnés seront stockées!!! Stash les changements locaux Appliquer Effacer @@ -610,28 +610,28 @@ Stashes CHANGEMENTS STASHES - Statistics + Statistiques COMMITS COMMITTER - MONTH - WEEK + MOIS + SEMAINE COMMITS: - AUTHORS: + AUTEURS : APERCU - SUBMODULES - Add Submodule - Copy Relative Path - Fetch nested submodules - Open Submodule Repository + SOUS-MODULES + Ajouter un sous-module + Copier le chemin relatif + Fetch les sous-modules imbriqués + Ouvrir le dépôt de sous-module Relative Path: Relative folder to store this module. - Delete Submodule + Supprimer le sous-module OK - Copy Tag Name + Copier le nom du Tag Copier le message du tag - Delete ${0}$... + Supprimer ${0}$... Fusionner ${0}$ dans ${1}$... - Push ${0}$... + Pousser ${0}$... URL : Actualiser les sous-modules Tous les sous-modules @@ -663,10 +663,10 @@ Amender Vous pouvez indexer ce fichier. COMMIT - COMMIT & PUSH + COMMIT & POUSSER Modèles/Historiques Trigger click event - Stage tous les changements et commit + Indexer tous les changements et commit Un commit vide a été détecté ! Voulez-vous continuer (--allow-empty) ? CONFLITS DÉTECTÉS LES CONFLITS DE FICHIER SONT RÉSOLUS diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index be929d98..45d89035 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -16,7 +16,7 @@ Существующую ветку Создать новую ветку Расположение: - Путь к рабочему каталогу. Поддерживается относительный путь. + Путь к рабочему каталогу (поддерживается относительный путь) Имя ветки: Имя целевого каталога по умолчанию. (необязательно) Отслеживание ветки: @@ -32,10 +32,10 @@ Выберите файл .patch для применения Игнорировать изменения пробелов Нет предупреждений - Отключает предупреждение о пробелах в конце + Отключить предупреждения о пробелах в конце Применить исправление - Предупреждение - Выдает предупреждения о нескольких таких ошибках, но применяет + Предупреждать + Выдавать предупреждения о нескольких таких ошибках, но применять Пробел: Архивировать... Сохранить архив в: @@ -51,7 +51,7 @@ РАССЛЕДОВАНИЕ В ЭТОМ ФАЙЛЕ НЕ ПОДДЕРЖИВАЕТСЯ!!! Проверить ${0}$... Сравнить с веткой - Сравнить с заголовком + Сравнить с ГОЛОВОЙ (HEAD) Сравнить с рабочим каталогом Копировать имя ветки Удалить ${0}$... @@ -81,7 +81,7 @@ Показывать в виде дерева файловой системы Проверить ветку Проверить ревизию - Предупреждение: При выполнении проверки ревизии ваша голова будет отсоединена + Предупреждение: После переключения ревизии ваша Голова (HEAD) будет отсоединена Ревизия: Ветка: Локальные изменения: @@ -96,19 +96,19 @@ Обычно вы не можете выделить слияние, потому что не знаете, какую сторону слияния следует считать основной. Эта опция позволяет отобразить изменение относительно указанного родительского элемента. Очистить отложенные Вы пытаетесь очистить все отложенные. Вы уверены, что хотите продолжить? - Клонировать внешнее хранилище + Клонировать внешний репозиторий Расширенные параметры: - Дополнительные аргументы для клонирования хранилища. (необязательно). + Дополнительные аргументы для клонирования репозитория. (необязательно). Локальное имя: - Имя хранилища. (необязательно). + Имя репозитория. (необязательно). Родительский каталог: - Адрес хранилища: + Адрес репозитория: ЗАКРЫТЬ Редактор Применить эту ревизию (cherry-pick) Применить несколько ревизий ... Переключиться на эту ревизию - Сравнить c HEAD + Сравнить c ГОЛОВОЙ (HEAD) Сравнить с рабочим каталогом Копировать информацию Копировать SHA @@ -144,7 +144,7 @@ Открыть в браузере Введите тему ревизии Описание - Настройка хранилища + Настройка репозитория ШАБЛОН РЕВИЗИИ Название: Cодержание: @@ -162,7 +162,7 @@ Автоматическое скачивание изменений Минут(а/ы) Разрешить '--signoff' для ревизии - Удалённое хранилище по-умолчанию + Внешний репозиторий по умолчанию Разрешить '--prune' при скачивании ОТСЛЕЖИВАНИЕ ПРОБЛЕМ Добавить пример правила для Git @@ -176,11 +176,11 @@ Пожалуйста, используйте $1, $2 для доступа к значениям групп регулярных выражений. ОТКРЫТЬ ИИ Предпочтительный сервис: - Если «Предпочтительный сервис» установлен, SourceGit будет использовать только этот хранилище. В противном случае, если доступно более одной услуги, будет отображено контекстное меню для выбора одной из них. + Если «Предпочтительный сервис» установлен, SourceGit будет использовать только этот репозиторий. В противном случае, если доступно более одной услуги, будет отображено контекстное меню для выбора одной из них. HTTP-прокси - HTTP-прокси, используемый этим хранилищем + HTTP-прокси для репозитория Имя пользователя - Имя пользователя для этого хранилища + Имя пользователя репозитория Рабочие пространства Имя Цвет @@ -213,7 +213,7 @@ Необязательно. Имя метки: Рекомендуемый формат: v1.0.0-alpha - Выложить на все внешние хранилища после создания + Выложить на все внешние репозитории после создания Создать новую метку Вид: Аннотированный @@ -222,12 +222,12 @@ Вырезать Удалить ветку Ветка: - Вы собираетесь удалить удалённую ветку!!! - Также удалите удалённую ветку ${0}$ + Вы собираетесь удалить внешнюю ветку!!! + Также удалите внешнюю ветку ${0}$ Удаление нескольких веток Вы пытаетесь удалить несколько веток одновременно. Обязательно перепроверьте, прежде чем предпринимать какие-либо действия! - Удалить внешнее хранилище - Внешнее хранилище: + Удалить внешний репозиторий + Внешний репозиторий: Цель: Подтвердите удаление группы Подтвердите удаление репозитория @@ -235,7 +235,7 @@ Путь подмодуля: Удалить метку Метка: - Удалить из внешнего хранилища + Удалить из внешнего репозитория РАЗНИЦА БИНАРНИКОВ НОВЫЙ СТАРЫЙ @@ -243,7 +243,7 @@ Режим файла изменён Игнорировать изменение пробелов Показывать скрытые символы - ИЗМЕНЕНИЕ ОБЪЕКТА ХБФ + ИЗМЕНЕНИЕ ОБЪЕКТА LFS Следующее различие НИКАКИХ ИЗМЕНЕНИЙ ИЛИ МЕНЯЕТСЯ ТОЛЬКО EOL Предыдущее различие @@ -271,17 +271,17 @@ Новое имя: Цель: Редактировать выбранную группу - Редактировать выбранное хранилище + Редактировать выбранный репозиторий Выполнить пользовательское действие Имя действия: Быстрая перемотка вперёд (без проверки) Извлечь - Извлечь все внешние хранилища + Извлечь все внешние репозитории Разрешить опцию '--force' Извлечь без меток - Внешнее хранилище: + Внешний репозиторий: Извлечь внешние изменения - Допустить без изменений + Не отслеживать Отклонить... Отклонить {0} файлов... Отменить изменения в выбранной(ых) строке(ах) @@ -324,30 +324,30 @@ Запуск выпуска... ПОТОК - Запуск выпуска Префикс метки версии: - Git хранилища больших файлов + Git LFS (хранилище больших файлов) Добавить шаблон отслеживания... Шаблон — это имя файла Изменить шаблон: - Добавить шаблон отслеживания в ХБФ Git + Добавить шаблон отслеживания в LFS Git Извлечь - Извлечь объекты ХБФ - Запустить «git lfs fetch», чтобы загрузить объекты ХБФ Git. При этом рабочая копия не обновляется. - Установить перехват ХБФ Git + Извлечь объекты LFS + Запустить «git lfs fetch», чтобы загрузить объекты LFS Git. При этом рабочая копия не обновляется. + Установить перехват LFS Git Показывать блокировки Нет заблокированных файлов Блокировка Показывать только мои блокировки - Блокировки ХБФ + Блокировки LFS Разблокировать Принудительно разблокировать Обрезать - Запустить «git lfs prune», чтобы удалить старые файлы ХБФ из локального хранилища + Запустить «git lfs prune», чтобы удалить старые файлы LFS из локального хранилища Забрать - Забрать объекты ХБФ - Запустить «git lfs pull», чтобы загрузить все файлы ХБФ Git для текущей ссылки и проверить + Забрать объекты LFS + Запустить «git lfs pull», чтобы загрузить все файлы LFS Git для текущей ссылки и проверить Выложить - Выложить объекты ХБФ - Отправляйте большие файлы, помещенные в очередь, в конечную точку ХБФ Git + Выложить объекты LFS + Отправляйте большие файлы, помещенные в очередь, в конечную точку LFS Git Внешнее хранилище: Отслеживать файлы с именем «{0}» Отслеживать все *{0} файлов @@ -371,7 +371,7 @@ Перейти на следующую вкладку Создать новую вкладку Открыть диалоговое окно настроек - ХРАНИЛИЩЕ + РЕПОЗИТОРИЙ Зафиксировать подготовленные изменения Зафиксировать и выложить подготовленные изменения Подготовить все изменения и зафиксировать @@ -379,7 +379,7 @@ Отклонить выбранные изменения Извлечение, запускается сразу Режим доски (по-умолчанию) - Принудительно перезагрузить хранилище + Принудительно перезагрузить репозиторий Забрать, запускается сразу Выложить, запускается сразу Подготовленные/Неподготовленные выбранные изменения @@ -395,7 +395,7 @@ Подготовить Снять из подготовленных Отклонить - Инициализировать хранилище + Инициализировать репозиторий Путь: Выполняется частичный перенос ревизий (cherry-pick). Обрабтка ревизии. @@ -432,8 +432,8 @@ Закрыть вкладку Закрыть другие вкладки Закрыть вкладки справа - Копировать путь хранилища - Хранилища + Копировать путь репозитория + Репозитории Вставить Сейчас {0} минут назад @@ -469,6 +469,7 @@ Инструмент ОСНОВНЫЕ Проверить обновления при старте + Формат даты Язык Максимальная длина истории Показывать время автора вместо времени ревизии на графике @@ -496,7 +497,7 @@ ОБОЛОЧКА/ТЕРМИНАЛ Оболочка/Терминал Путь - Удалить внешнее хранилище + Удалить внешний репозиторий Цель: Удалить рабочий каталог Информация об обрезке рабочего каталога в «$GIT_DIR/worktrees» @@ -509,21 +510,21 @@ Ничего не делать Отложить и применить повторно Забрать без меток - Внешнее хранилище: + Внешний репозиторий: Забрать (Получить и слить) Использовать перемещение вместо слияния Выложить Убедитесь, что подмодули были вставлены Принудительно выложить Локальная ветка: - Внешнее хранилище: - Выложить изменения на внешнее хранилище - Ветка внешнего хранилища: + Внешний репозиторий: + Выложить изменения на внешний репозиторий + Ветка внешнего репозитория: Отслеживать ветку Выложить все метки - Выложить метку на внешнее хранилище - Выложить на все внешние хранилища - Внешнее хранилище: + Выложить метку на внешний репозиторий + Выложить на все внешние репозитории + Внешний репозиторий: Метка: Выйти Перемещение текущей ветки @@ -531,12 +532,12 @@ На: Переместить: Обновить - Добавить внешнее хранилище - Редактировать внешнее хранилище + Добавить внешний репозиторий + Редактировать внешний репозиторий Имя: - Имя внешнего хранилища - Адрес хранилища: - Адрес внешнего хранилища git + Имя внешнего репозитория + Адрес репозитория: + Адрес внешнего репозитория git Копировать адрес Удалить... Редактировать... @@ -551,11 +552,11 @@ Уникальное имя для данной ветки Ветка: Отказ - Автоматическое извлечение изменений с внешних хранилищ... + Автоматическое извлечение изменений с внешних репозиторий... Очистить (Сбор мусора и удаление) - Запустить команду «git gc» для данного хранилища. + Запустить команду «git gc» для данного репозитория. Очистить всё - Настройка хранилища + Настройка репозитория ПРОДОЛЖИТЬ Изменить действия Не изменять действия @@ -571,14 +572,14 @@ Дата ревизии (--date-order) Топологически (--topo-order) ЛОКАЛЬНЫЕ ВЕТКИ - Навигация по заголовку + Навигация по ГОЛОВЕ (HEAD) Включить опцию --first-parent Создать ветку Открыть в {0} Открыть в расширенном инструменте Обновить - ВНЕШНИЕ ХРАНИЛИЩА - ДОБАВИТЬ ВНЕШНЕЕ ХРАНИЛИЩЕ + ВНЕШНИЕ РЕПОЗИТОРИИ + ДОБАВИТЬ ВНЕШНИЙ РЕПОЗИТОРИЙ Поиск ревизии Файл Сообщение @@ -612,7 +613,7 @@ СОХРАНИТЬ Сохранить как... Исправление успешно сохранено! - Сканирование хранилищ + Сканирование репозиторий Корневой каталог: Копировать SHA Перейти @@ -656,7 +657,7 @@ Добавить подмодули Копировать относительный путь Извлечение вложенных подмодулей - Открыть подмодуль хранилища + Открыть подмодуль репозитория Относительный путь: Относительный каталог для хранения подмодуля. Удалить подмодуль @@ -677,16 +678,16 @@ Приветствие Создать группу Создать подгруппу - Клонировать хранилище + Клонировать репозиторий Удалить ПОДДЕРЖИВАЕТСЯ: ПЕРЕТАСКИВАНИЕ КАТАЛОГОВ, ПОЛЬЗОВАТЕЛЬСКАЯ ГРУППИРОВКА. Редактировать Перейти в другую группу - Открыть все хранилища - Открыть хранилище + Открыть все репозитории + Открыть репозиторий Открыть терминал - Повторное сканирование хранилищ в каталоге клонирования по умолчанию - Поиск хранилищ... + Повторное сканирование репозиториев в каталоге клонирования по умолчанию + Поиск репозиториев... Сортировка Изменения Игнорировать Git diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index e53af9a8..5780f140 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -469,6 +469,7 @@ 工具 通用配置 启动时检测软件更新 + 日期时间格式 显示语言 最大历史提交数 在提交路线图中显示修改时间而非提交时间 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index e96f68ad..4704b8f0 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -468,6 +468,7 @@ 工具 一般設定 啟動時檢查軟體更新 + 日期時間格式 顯示語言 最大歷史提交數 在提交路線圖中顯示修改時間而非提交時間 diff --git a/src/SourceGit.csproj b/src/SourceGit.csproj index 8e8c2b3f..64168b2e 100644 --- a/src/SourceGit.csproj +++ b/src/SourceGit.csproj @@ -20,7 +20,7 @@ Public - + true true link @@ -30,10 +30,6 @@ $(DefineConstants);DISABLE_UPDATE_DETECTION - - $(DefineConstants);ENABLE_PORTABLE - - diff --git a/src/ViewModels/Archive.cs b/src/ViewModels/Archive.cs index 366a6179..0a180b71 100644 --- a/src/ViewModels/Archive.cs +++ b/src/ViewModels/Archive.cs @@ -23,7 +23,7 @@ namespace SourceGit.ViewModels { _repo = repo; _revision = branch.Head; - _saveFile = $"archive-{Path.GetFileNameWithoutExtension(branch.Name)}.zip"; + _saveFile = $"archive-{Path.GetFileName(branch.Name)}.zip"; BasedOn = branch; View = new Views.Archive() { DataContext = this }; } @@ -41,7 +41,7 @@ namespace SourceGit.ViewModels { _repo = repo; _revision = tag.SHA; - _saveFile = $"archive-{tag.Name}.zip"; + _saveFile = $"archive-{Path.GetFileName(tag.Name)}.zip"; BasedOn = tag; View = new Views.Archive() { DataContext = this }; } diff --git a/src/ViewModels/Checkout.cs b/src/ViewModels/Checkout.cs index 713c260f..fd84682a 100644 --- a/src/ViewModels/Checkout.cs +++ b/src/ViewModels/Checkout.cs @@ -65,7 +65,7 @@ namespace SourceGit.ViewModels { var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch); if (b != null && _repo.HistoriesFilterMode == Models.FilterMode.Included) - _repo.Settings.UpdateHistoriesFilter(b.FullName, Models.FilterType.LocalBranch, Models.FilterMode.Included); + _repo.SetBranchFilterMode(b, Models.FilterMode.Included, true, false); _repo.MarkBranchesDirtyManually(); _repo.SetWatcherEnabled(true); diff --git a/src/ViewModels/CreateBranch.cs b/src/ViewModels/CreateBranch.cs index 653d2db8..3560ea8d 100644 --- a/src/ViewModels/CreateBranch.cs +++ b/src/ViewModels/CreateBranch.cs @@ -83,6 +83,7 @@ namespace SourceGit.ViewModels _repo.SetWatcherEnabled(false); return Task.Run(() => { + var succ = false; if (CheckoutAfterCreated) { var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result(); @@ -92,7 +93,7 @@ namespace SourceGit.ViewModels if (PreAction == Models.DealWithLocalChanges.StashAndReaply) { SetProgressDescription("Stash local changes"); - var succ = new Commands.Stash(_repo.FullPath).Push("CREATE_BRANCH_AUTO_STASH"); + succ = new Commands.Stash(_repo.FullPath).Push("CREATE_BRANCH_AUTO_STASH"); if (!succ) { CallUIThread(() => _repo.SetWatcherEnabled(true)); @@ -109,7 +110,7 @@ namespace SourceGit.ViewModels } SetProgressDescription($"Create new branch '{_name}'"); - new Commands.Checkout(_repo.FullPath).Branch(_name, _baseOnRevision, SetProgressDescription); + succ = new Commands.Checkout(_repo.FullPath).Branch(_name, _baseOnRevision, SetProgressDescription); if (needPopStash) { @@ -120,17 +121,24 @@ namespace SourceGit.ViewModels else { SetProgressDescription($"Create new branch '{_name}'"); - Commands.Branch.Create(_repo.FullPath, _name, _baseOnRevision); + succ = Commands.Branch.Create(_repo.FullPath, _name, _baseOnRevision); } CallUIThread(() => { - if (CheckoutAfterCreated && _repo.HistoriesFilterMode == Models.FilterMode.Included) - _repo.Settings.UpdateHistoriesFilter($"refs/heads/{_name}", Models.FilterType.LocalBranch, Models.FilterMode.Included); + if (succ && CheckoutAfterCreated && _repo.HistoriesFilterMode == Models.FilterMode.Included) + { + var fake = new Models.Branch() { IsLocal = true, FullName = $"refs/heads/{_name}" }; + if (BasedOn is Models.Branch based && !based.IsLocal) + fake.Upstream = based.FullName; + + _repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false); + } _repo.MarkBranchesDirtyManually(); _repo.SetWatcherEnabled(true); }); + return true; }); } diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 59f420eb..c5cb23e9 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -768,7 +768,7 @@ namespace SourceGit.ViewModels exclude.Header = App.Text("Repository.FilterCommits.Exclude"); exclude.Click += (_, e) => { - _repo.SetBranchFilterMode(branch, Models.FilterMode.Excluded); + _repo.SetBranchFilterMode(branch, Models.FilterMode.Excluded, false, true); e.Handled = true; }; @@ -780,7 +780,7 @@ namespace SourceGit.ViewModels include.Header = App.Text("Repository.FilterCommits.Include"); include.Click += (_, e) => { - _repo.SetBranchFilterMode(branch, Models.FilterMode.Included); + _repo.SetBranchFilterMode(branch, Models.FilterMode.Included, false, true); e.Handled = true; }; visibility.Items.Add(include); @@ -792,7 +792,7 @@ namespace SourceGit.ViewModels unset.Header = App.Text("Repository.FilterCommits.Default"); unset.Click += (_, e) => { - _repo.SetBranchFilterMode(branch, Models.FilterMode.None); + _repo.SetBranchFilterMode(branch, Models.FilterMode.None, false, true); e.Handled = true; }; visibility.Items.Add(exclude); diff --git a/src/ViewModels/Preference.cs b/src/ViewModels/Preference.cs index 04f0fa91..efd446df 100644 --- a/src/ViewModels/Preference.cs +++ b/src/ViewModels/Preference.cs @@ -129,6 +129,21 @@ namespace SourceGit.ViewModels 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 { get => _useFixedTabWidth; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 82197bdf..bc86147e 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -770,21 +770,27 @@ namespace SourceGit.ViewModels { var changed = _settings.UpdateHistoriesFilter(tag.Name, Models.FilterType.Tag, mode); if (changed) - RefreshHistoriesFilters(); + RefreshHistoriesFilters(true); } - public void SetBranchFilterMode(Models.Branch branch, Models.FilterMode mode) + public void SetBranchFilterMode(Models.Branch branch, Models.FilterMode mode, bool clearExists, bool refresh) { var node = FindBranchNode(branch.IsLocal ? _localBranchTrees : _remoteBranchTrees, branch.FullName); if (node != null) - SetBranchFilterMode(node, mode); + SetBranchFilterMode(node, mode, clearExists, refresh); } - public void SetBranchFilterMode(BranchTreeNode node, Models.FilterMode mode) + public void SetBranchFilterMode(BranchTreeNode node, Models.FilterMode mode, bool clearExists, bool refresh) { var isLocal = node.Path.StartsWith("refs/heads/", StringComparison.Ordinal); var tree = isLocal ? _localBranchTrees : _remoteBranchTrees; + if (clearExists) + { + _settings.HistoriesFilters.Clear(); + HistoriesFilterMode = Models.FilterMode.None; + } + if (node.Backend is Models.Branch branch) { var type = isLocal ? Models.FilterType.LocalBranch : Models.FilterType.RemoteBranch; @@ -822,7 +828,7 @@ namespace SourceGit.ViewModels cur = parent; } while (true); - RefreshHistoriesFilters(); + RefreshHistoriesFilters(refresh); } public void StashAll(bool autoStart) @@ -2149,18 +2155,21 @@ namespace SourceGit.ViewModels return visible; } - private void RefreshHistoriesFilters() + private void RefreshHistoriesFilters(bool refresh) { - var filters = _settings.CollectHistoriesFilters(); - UpdateBranchTreeFilterMode(LocalBranchTrees, filters); - UpdateBranchTreeFilterMode(RemoteBranchTrees, filters); - UpdateTagFilterMode(filters); - if (_settings.HistoriesFilters.Count > 0) HistoriesFilterMode = _settings.HistoriesFilters[0].Mode; else HistoriesFilterMode = Models.FilterMode.None; + if (!refresh) + return; + + var filters = _settings.CollectHistoriesFilters(); + UpdateBranchTreeFilterMode(LocalBranchTrees, filters); + UpdateBranchTreeFilterMode(RemoteBranchTrees, filters); + UpdateTagFilterMode(filters); + Task.Run(RefreshCommits); } diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 59de9245..a1230715 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -82,6 +82,10 @@ namespace SourceGit.ViewModels CommitMessage = new Commands.QueryCommitFullMessage(_repo.FullPath, currentBranch.Head).Result(); } + else + { + CommitMessage = string.Empty; + } Staged = GetStagedChanges(); SelectedStaged = []; @@ -1351,8 +1355,9 @@ namespace SourceGit.ViewModels { var menu = new ContextMenu(); + var gitTemplate = new Commands.Config(_repo.FullPath).Get("commit.template"); var templateCount = _repo.Settings.CommitTemplates.Count; - if (templateCount == 0) + if (templateCount == 0 && string.IsNullOrEmpty(gitTemplate)) { menu.Items.Add(new MenuItem() { @@ -1376,6 +1381,29 @@ namespace SourceGit.ViewModels }; 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 = "-" }); diff --git a/src/Views/Blame.axaml.cs b/src/Views/Blame.axaml.cs index d32e4370..1784efc1 100644 --- a/src/Views/Blame.axaml.cs +++ b/src/Views/Blame.axaml.cs @@ -37,6 +37,7 @@ namespace SourceGit.Views { var typeface = view.CreateTypeface(); var underlinePen = new Pen(Brushes.DarkOrange); + var width = Bounds.Width; 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)); 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( info.Author, CultureInfo.CurrentCulture, @@ -82,6 +73,15 @@ namespace SourceGit.Views _editor.FontSize, _editor.Foreground); 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); 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( info.Author, CultureInfo.CurrentCulture, @@ -132,7 +123,16 @@ namespace SourceGit.Views typeface, _editor.FontSize, _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) maxWidth = x; diff --git a/src/Views/FileHistories.axaml b/src/Views/FileHistories.axaml index 8403ae73..b0706d24 100644 --- a/src/Views/FileHistories.axaml +++ b/src/Views/FileHistories.axaml @@ -78,7 +78,7 @@ - + - + diff --git a/src/Views/FilterModeSwitchButton.axaml.cs b/src/Views/FilterModeSwitchButton.axaml.cs index f68e9166..1d1ae30c 100644 --- a/src/Views/FilterModeSwitchButton.axaml.cs +++ b/src/Views/FilterModeSwitchButton.axaml.cs @@ -120,7 +120,7 @@ namespace SourceGit.Views unset.Header = App.Text("Repository.FilterCommits.Default"); unset.Click += (_, ev) => { - repo.SetBranchFilterMode(node, Models.FilterMode.None); + repo.SetBranchFilterMode(node, Models.FilterMode.None, false, true); ev.Handled = true; }; @@ -134,7 +134,7 @@ namespace SourceGit.Views include.IsEnabled = mode != Models.FilterMode.Included; include.Click += (_, ev) => { - repo.SetBranchFilterMode(node, Models.FilterMode.Included); + repo.SetBranchFilterMode(node, Models.FilterMode.Included, false, true); ev.Handled = true; }; @@ -144,7 +144,7 @@ namespace SourceGit.Views exclude.IsEnabled = mode != Models.FilterMode.Excluded; exclude.Click += (_, ev) => { - repo.SetBranchFilterMode(node, Models.FilterMode.Excluded); + repo.SetBranchFilterMode(node, Models.FilterMode.Excluded, false, true); ev.Handled = true; }; diff --git a/src/Views/Histories.axaml b/src/Views/Histories.axaml index 20f49d90..d7afe6ae 100644 --- a/src/Views/Histories.axaml +++ b/src/Views/Histories.axaml @@ -191,7 +191,8 @@ FontWeight="{Binding FontWeight}" Opacity="{Binding Opacity}" 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}"/> diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index fbb907d9..87ae11cb 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -343,6 +343,15 @@ namespace SourceGit.Views set => SetValue(ShowAsDateTimeProperty, value); } + public static readonly StyledProperty DateTimeFormatProperty = + AvaloniaProperty.Register(nameof(DateTimeFormat), 0); + + public int DateTimeFormat + { + get => GetValue(DateTimeFormatProperty); + set => SetValue(DateTimeFormatProperty, value); + } + public static readonly StyledProperty UseAuthorTimeProperty = AvaloniaProperty.Register(nameof(UseAuthorTime), true); @@ -371,6 +380,11 @@ namespace SourceGit.Views else StartTimer(); } + else if (change.Property == DateTimeFormatProperty) + { + if (ShowAsDateTime) + SetCurrentValue(TextProperty, GetDisplayText()); + } } protected override void OnLoaded(RoutedEventArgs e) @@ -426,10 +440,10 @@ namespace SourceGit.Views if (commit == null) return string.Empty; - var timestamp = UseAuthorTime ? commit.AuthorTime : commit.CommitterTime; 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 localTime = DateTime.UnixEpoch.AddSeconds(timestamp).ToLocalTime(); var span = now - localTime; diff --git a/src/Views/InteractiveRebase.axaml b/src/Views/InteractiveRebase.axaml index b9819c38..0a5a01ea 100644 --- a/src/Views/InteractiveRebase.axaml +++ b/src/Views/InteractiveRebase.axaml @@ -77,7 +77,7 @@ - + - + - + + + + + + + + + + + + + - @@ -74,11 +94,11 @@ - - - - + - - - - + + +