Compare commits

...

7 commits

Author SHA1 Message Date
leo
2f9e825b63
refactor: pass Models.Commit instead of just sha of it
Some checks are pending
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) Waiting to run
Signed-off-by: leo <longshuang@msn.cn>
2024-11-01 18:10:22 +08:00
leo
ba3c72585d
enhance: use Inter as default font for all platforms (#639)
Signed-off-by: leo <longshuang@msn.cn>
2024-11-01 17:54:21 +08:00
github-actions[bot]
26fe56e065 doc: Update translation status and missing keys 2024-11-01 09:25:17 +00:00
leo
a36058ec51
feature: supports custom actions (#638)
Signed-off-by: leo <longshuang@msn.cn>
2024-11-01 17:23:31 +08:00
leo
7c5de7e48c
enhance: do NOT restore fullscreen window on macOS
Signed-off-by: leo <longshuang@msn.cn>
2024-11-01 12:22:47 +08:00
leo
98612b0024
code_style: remove unused code
Signed-off-by: leo <longshuang@msn.cn>
2024-11-01 10:00:37 +08:00
leo
e3c0f7d496
refactor: rewrite chromeless window (#634)
* use system chrome instead of custom caption button on macOS
* move `BeginMoveWindow` and `MaximizeOrRestoreWindow` to `ChromelessWindow`
* better supports for fullscreen mode on macOS
* redesign the layout of title bar for all windows

Signed-off-by: leo <longshuang@msn.cn>
2024-11-01 09:38:42 +08:00
62 changed files with 748 additions and 669 deletions

View file

@ -47,7 +47,7 @@
## 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-97.91%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-98.96%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-89.42%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-92.55%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-96.05%25-yellow)](TRANSLATION.md) [![es__ES](https://img.shields.io/badge/es__ES-97.08%25-yellow)](TRANSLATION.md) [![fr__FR](https://img.shields.io/badge/fr__FR-87.72%25-yellow)](TRANSLATION.md) [![pt__BR](https://img.shields.io/badge/pt__BR-90.79%25-yellow)](TRANSLATION.md) [![ru__RU](https://img.shields.io/badge/ru__RU-98.10%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

View file

@ -1,4 +1,4 @@
### de_DE.axaml: 97.91%
### de_DE.axaml: 96.05%
<details>
@ -6,6 +6,15 @@
- Text.BranchCM.FetchInto
- Text.ChangeCM.GenerateCommitMessage
- Text.CommitCM.CustomAction
- Text.Configure.CustomAction
- Text.Configure.CustomAction.Arguments
- Text.Configure.CustomAction.Arguments.Tip
- Text.Configure.CustomAction.Executable
- Text.Configure.CustomAction.Name
- Text.Configure.CustomAction.Scope
- Text.Configure.CustomAction.Scope.Commit
- Text.Configure.CustomAction.Scope.Repository
- Text.Configure.Git.EnablePruneOnFetch
- Text.Configure.Git.EnableSignOff
- Text.Configure.IssueTracker.AddSampleGitLabIssue
@ -13,31 +22,48 @@
- Text.Configure.OpenAI
- Text.Configure.OpenAI.Prefered
- Text.Configure.OpenAI.Prefered.Tip
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.Preference.AI.AnalyzeDiffPrompt
- Text.Preference.AI.GenerateSubjectPrompt
- Text.Preference.AI.Name
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Stash.KeepIndex
- Text.WorkingCopy.ConfirmCommitWithoutFiles
</details>
### es_ES.axaml: 98.96%
### es_ES.axaml: 97.08%
<details>
<summary>Missing Keys</summary>
- Text.ChangeCM.GenerateCommitMessage
- Text.CommitCM.CustomAction
- Text.Configure.CustomAction
- Text.Configure.CustomAction.Arguments
- Text.Configure.CustomAction.Arguments.Tip
- Text.Configure.CustomAction.Executable
- Text.Configure.CustomAction.Name
- Text.Configure.CustomAction.Scope
- Text.Configure.CustomAction.Scope.Commit
- Text.Configure.CustomAction.Scope.Repository
- Text.Configure.Git.EnablePruneOnFetch
- Text.Configure.OpenAI
- Text.Configure.OpenAI.Prefered
- Text.Configure.OpenAI.Prefered.Tip
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.Preference.AI.Name
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Stash.KeepIndex
</details>
### fr_FR.axaml: 89.42%
### fr_FR.axaml: 87.72%
<details>
@ -52,8 +78,17 @@
- Text.CherryPick.Mainline
- Text.CherryPick.Mainline.Tips
- Text.CommitCM.CherryPickMultiple
- Text.CommitCM.CustomAction
- Text.CommitCM.SquashCommitsSinceThis
- Text.CommitDetail.Info.WebLinks
- Text.Configure.CustomAction
- Text.Configure.CustomAction.Arguments
- Text.Configure.CustomAction.Arguments.Tip
- Text.Configure.CustomAction.Executable
- Text.Configure.CustomAction.Name
- Text.Configure.CustomAction.Scope
- Text.Configure.CustomAction.Scope.Commit
- Text.Configure.CustomAction.Scope.Repository
- Text.Configure.Git.DefaultRemote
- Text.Configure.Git.EnablePruneOnFetch
- Text.Configure.Git.EnableSignOff
@ -74,6 +109,8 @@
- Text.ConventionalCommit.Type
- Text.Diff.IgnoreWhitespace
- Text.Discard.IncludeIgnored
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.FileHistory.FileChange
- Text.GitLFS.Locks.OnlyMine
- Text.Histories.Header.AuthorTime
@ -97,6 +134,8 @@
- Text.Preference.Shell.Type
- Text.Preference.Shell.Path
- Text.Repository.AutoFetching
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Repository.EnableReflog
- Text.Repository.Search.InCurrentBranch
- Text.ScanRepositories
@ -117,7 +156,7 @@
</details>
### pt_BR.axaml: 92.55%
### pt_BR.axaml: 90.79%
<details>
@ -132,10 +171,19 @@
- Text.CherryPick.Mainline
- Text.CherryPick.Mainline.Tips
- Text.CommitCM.CherryPickMultiple
- Text.CommitCM.CustomAction
- Text.CommitCM.SquashCommitsSinceThis
- Text.CommitDetail.Info.ContainsIn
- Text.CommitDetail.Info.ContainsIn.Title
- Text.CommitDetail.Info.WebLinks
- Text.Configure.CustomAction
- Text.Configure.CustomAction.Arguments
- Text.Configure.CustomAction.Arguments.Tip
- Text.Configure.CustomAction.Executable
- Text.Configure.CustomAction.Name
- Text.Configure.CustomAction.Scope
- Text.Configure.CustomAction.Scope.Commit
- Text.Configure.CustomAction.Scope.Repository
- Text.Configure.Git.DefaultRemote
- Text.Configure.Git.EnablePruneOnFetch
- Text.Configure.Git.EnableSignOff
@ -156,6 +204,8 @@
- Text.ConventionalCommit.Type
- Text.CopyAllText
- Text.Discard.IncludeIgnored
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.FileHistory.FileContent
- Text.FileHistory.FileChange
- Text.GitLFS.Locks.OnlyMine
@ -163,6 +213,8 @@
- Text.MoveRepositoryNode.Target
- Text.Preference.AI.Name
- Text.Push.CheckSubmodules
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
- Text.Squash.Into
- Text.Stash.KeepIndex
- Text.Stash.OnlyStagedChanges
@ -176,13 +228,25 @@
</details>
### ru_RU.axaml: 100.00%
### ru_RU.axaml: 98.10%
<details>
<summary>Missing Keys</summary>
- Text.CommitCM.CustomAction
- Text.Configure.CustomAction
- Text.Configure.CustomAction.Arguments
- Text.Configure.CustomAction.Arguments.Tip
- Text.Configure.CustomAction.Executable
- Text.Configure.CustomAction.Name
- Text.Configure.CustomAction.Scope
- Text.Configure.CustomAction.Scope.Commit
- Text.Configure.CustomAction.Scope.Repository
- Text.ExecuteCustomAction
- Text.ExecuteCustomAction.Name
- Text.Repository.CustomActions
- Text.Repository.CustomActions.Empty
</details>

View file

@ -59,6 +59,10 @@ namespace SourceGit
builder.UsePlatformDetect();
builder.LogToTrace();
builder.WithInterFont();
builder.With(new FontManagerOptions()
{
DefaultFamilyName = "fonts:Inter#Inter"
});
builder.ConfigureFonts(manager =>
{
var monospace = new EmbeddedFontCollection(
@ -223,7 +227,7 @@ namespace SourceGit
if (onlyUseMonospaceFontInEditor)
{
if (string.IsNullOrEmpty(defaultFont))
resDic.Add("Fonts.Primary", new FontFamily("fonts:Inter#Inter, $Default"));
resDic.Add("Fonts.Primary", new FontFamily("fonts:Inter#Inter"));
else
resDic.Add("Fonts.Primary", new FontFamily(defaultFont));
}

View file

@ -0,0 +1,63 @@
using System;
using System.Diagnostics;
using System.Text;
using Avalonia.Threading;
namespace SourceGit.Commands
{
public static class ExecuteCustomAction
{
public static void Run(string repo, string file, string args, Action<string> outputHandler)
{
var start = new ProcessStartInfo();
start.FileName = file;
start.Arguments = args;
start.UseShellExecute = false;
start.CreateNoWindow = true;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.StandardOutputEncoding = Encoding.UTF8;
start.StandardErrorEncoding = Encoding.UTF8;
start.WorkingDirectory = repo;
// Force using en_US.UTF-8 locale to avoid GCM crash
if (OperatingSystem.IsLinux())
start.Environment.Add("LANG", "en_US.UTF-8");
// Fix macOS `PATH` env
if (OperatingSystem.IsMacOS() && !string.IsNullOrEmpty(Native.OS.CustomPathEnv))
start.Environment.Add("PATH", Native.OS.CustomPathEnv);
var proc = new Process() { StartInfo = start };
proc.OutputDataReceived += (_, e) =>
{
if (e.Data != null)
outputHandler?.Invoke(e.Data);
};
proc.ErrorDataReceived += (_, e) =>
{
if (e.Data != null)
outputHandler?.Invoke(e.Data);
};
try
{
proc.Start();
}
catch (Exception e)
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, e.Message);
});
}
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
proc.WaitForExit();
proc.Close();
}
}
}

View file

@ -0,0 +1,42 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.Models
{
public enum CustomActionScope
{
Repository,
Commit,
}
public class CustomAction : ObservableObject
{
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
public CustomActionScope Scope
{
get => _scope;
set => SetProperty(ref _scope, value);
}
public string Executable
{
get => _executable;
set => SetProperty(ref _executable, value);
}
public string Arguments
{
get => _arguments;
set => SetProperty(ref _arguments, value);
}
private string _name = string.Empty;
private CustomActionScope _scope = CustomActionScope.Repository;
private string _executable = string.Empty;
private string _arguments = string.Empty;
}
}

View file

@ -100,6 +100,12 @@ namespace SourceGit.Models
set;
} = new AvaloniaList<IssueTrackerRule>();
public AvaloniaList<CustomAction> CustomActions
{
get;
set;
} = new AvaloniaList<CustomAction>();
public bool EnableAutoFetch
{
get;
@ -230,5 +236,22 @@ namespace SourceGit.Models
if (rule != null)
IssueTrackerRules.Remove(rule);
}
public CustomAction AddNewCustomAction()
{
var act = new CustomAction()
{
Name = "Unnamed Custom Action",
};
CustomActions.Add(act);
return act;
}
public void RemoveCustomAction(CustomAction act)
{
if (act != null)
CustomActions.Remove(act);
}
}
}

View file

@ -1,4 +1,5 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StreamGeometry x:Key="Icons.Action">M41 512c0-128 46-241 138-333C271 87 384 41 512 41s241 46 333 138c92 92 138 205 138 333s-46 241-138 333c-92 92-205 138-333 138s-241-46-333-138C87 753 41 640 41 512zm87 0c0 108 36 195 113 271s164 113 271 113c108 0 195-36 271-113s113-164 113-271-36-195-113-271c-77-77-164-113-271-113-108 0-195 36-271 113C164 317 128 404 128 512zm256 148V292l195 113L768 512l-195 113-195 113v-77zm148-113-61 36V440l61 36 61 36-61 36z</StreamGeometry>
<StreamGeometry x:Key="Icons.AIAssist">M951 419a255 255 0 00-22-209 258 258 0 00-278-124A259 259 0 00213 178a255 255 0 00-171 124 258 258 0 0032 303 255 255 0 0022 210 258 258 0 00278 124A255 255 0 00566 1024a258 258 0 00246-179 256 256 0 00171-124 258 258 0 00-32-302zM566 957a191 191 0 01-123-44l6-3 204-118a34 34 0 0017-29v-287l86 50a3 3 0 012 2v238a192 192 0 01-192 192zM154 781a191 191 0 01-23-129l6 4 204 118a33 33 0 0033 0l249-144v99a3 3 0 01-1 3L416 851a192 192 0 01-262-70zM100 337a191 191 0 01101-84V495a33 33 0 0017 29l248 143-86 50a3 3 0 01-3 0l-206-119A192 192 0 01100 336zm708 164-249-145L645 307a3 3 0 013 0l206 119a192 192 0 01-29 346v-242a34 34 0 00-17-28zm86-129-6-4-204-119a33 33 0 00-33 0L401 394V294a3 3 0 011-3l206-119a192 192 0 01285 199zm-539 176-86-50a3 3 0 01-2-2V259a192 192 0 01315-147l-6 3-204 118a34 34 0 00-17 29zm47-101 111-64 111 64v128l-111 64-111-64z</StreamGeometry>
<StreamGeometry x:Key="Icons.Archive">M296 392h64v64h-64zM296 582v160h128V582h-64v-62h-64v62zm80 48v64h-32v-64h32zM360 328h64v64h-64zM296 264h64v64h-64zM360 456h64v64h-64zM360 200h64v64h-64zM855 289 639 73c-6-6-14-9-23-9H192c-18 0-32 14-32 32v832c0 18 14 32 32 32h640c18 0 32-14 32-32V311c0-9-3-17-9-23zM790 326H602V138L790 326zm2 562H232V136h64v64h64v-64h174v216c0 23 19 42 42 42h216v494z</StreamGeometry>
<StreamGeometry x:Key="Icons.Binary">M71 1024V0h661L953 219V1024H71zm808-731-220-219H145V951h735V293zM439 512h-220V219h220V512zm-74-219H292v146h74v-146zm0 512h74v73h-220v-73H292v-146H218V585h147v219zm294-366h74V512H512v-73h74v-146H512V219h147v219zm74 439H512V585h220v293zm-74-219h-74v146h74v-146z</StreamGeometry>
@ -71,9 +72,6 @@
<StreamGeometry x:Key="Icons.Loading">M512 0C233 0 7 223 0 500C6 258 190 64 416 64c230 0 416 200 416 448c0 53 43 96 96 96s96-43 96-96c0-283-229-512-512-512zm0 1023c279 0 505-223 512-500c-6 242-190 436-416 436c-230 0-416-200-416-448c0-53-43-96-96-96s-96 43-96 96c0 283 229 512 512 512z</StreamGeometry>
<StreamGeometry x:Key="Icons.Local">M976 0h-928A48 48 0 000 48v652a48 48 0 0048 48h416V928H200a48 48 0 000 96h624a48 48 0 000-96H560v-180h416a48 48 0 0048-48V48A48 48 0 00976 0zM928 652H96V96h832v556z</StreamGeometry>
<StreamGeometry x:Key="Icons.Lock">M832 464h-68V240a128 128 0 00-128-128h-248a128 128 0 00-128 128v224H192c-18 0-32 14-32 32v384c0 18 14 32 32 32h640c18 0 32-14 32-32v-384c0-18-14-32-32-32zm-292 237v53a8 8 0 01-8 8h-40a8 8 0 01-8-8v-53a48 48 0 1156 0zm152-237H332V240a56 56 0 0156-56h248a56 56 0 0156 56v224z</StreamGeometry>
<StreamGeometry x:Key="Icons.MacOS.Close">M887 774 625 511l263-260c11-11 11-28 0-39l-75-75c-5-5-12-8-20-8-7 0-14 3-20 8L512 396 250 137c-5-5-12-8-20-8-7 0-14 3-20 8L136 212c-11 11-11 28 0 39l263 260L137 774c-5 5-8 12-8 20 0 7 3 14 8 20l75 75c5 5 12 8 20 8 7 0 14-3 20-8L512 626l261 262c5 5 12 8 20 8 7 0 14-3 20-8l75-75c5-5 8-12 8-20C895 786 892 779 887 774z</StreamGeometry>
<StreamGeometry x:Key="Icons.MacOS.Minimize">M1024 750v110c0 50-41 91-91 91h-841A92 92 0 010 859v-110C0 699 41 658 91 658h841c50 0 91 41 91 91z</StreamGeometry>
<StreamGeometry x:Key="Icons.MacOS.Maximize">M0 4 0 20 16 20 0 4M4 0 20 0 20 16 4 0z</StreamGeometry>
<StreamGeometry x:Key="Icons.Menu">M192 192m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM192 512m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM192 832m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0ZM864 160H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32zM864 480H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32zM864 800H352c-17.7 0-32 14.3-32 32s14.3 32 32 32h512c17.7 0 32-14.3 32-32s-14.3-32-32-32z</StreamGeometry>
<StreamGeometry x:Key="Icons.Merge">M824 645V307c0-56-46-102-102-102h-102V102l-154 154 154 154V307h102v338c-46 20-82 67-82 123 0 72 61 133 133 133 72 0 133-61 133-133 0-56-36-102-82-123zm-51 195c-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72s-31 72-72 72zM384 256c0-72-61-133-133-133-72 0-133 61-133 133 0 56 36 102 82 123v266C154 666 118 712 118 768c0 72 61 133 133 133 72 0 133-61 133-133 0-56-36-102-82-123V379C348 358 384 312 384 256zM323 768c0 41-31 72-72 72-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72zM251 328c-41 0-72-31-72-72s31-72 72-72c41 0 72 31 72 72s-31 72-72 72z</StreamGeometry>
<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>

View file

@ -108,6 +108,7 @@
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Copy Info</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">Copy SHA</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Custom Action</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactive Rebase ${0}$ to Here</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">Rebase ${0}$ to Here</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">Reset ${0}$ to Here</x:String>
@ -139,6 +140,14 @@
<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 Content:</x:String>
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">CUSTOM ACTION</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">Arguments:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">${REPO} - Repository's path; ${SHA} - Selected commit's SHA</x:String>
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">Executable File:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">Name:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">Scope:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Address</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email address</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
@ -252,6 +261,8 @@
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">Edit Selected Group</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">Edit Selected Repository</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">Run Custom Action</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">Action Name:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without 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 all remotes</x:String>
@ -516,6 +527,8 @@
<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.CustomActions" xml:space="preserve">Custom Actions</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">No Custom Actions</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">Enable '--reflog' Option</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open In File Browser</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">Search Branches/Tags/Submodules</x:String>

View file

@ -111,6 +111,7 @@
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">复制简要信息</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">复制提交指纹</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">自定义操作</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">交互式变基(rebase -i) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 到此处</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重置(reset) ${0}$ 到此处</x:String>
@ -142,6 +143,14 @@
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交信息模板</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">模板名 </x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">模板内容 </x:String>
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">自定义操作</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">命令行参数 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">请使用${REPO}代替仓库路径,${SHA}代替提交哈希</x:String>
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">可执行文件路径 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">名称 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">作用目标 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">选中的提交</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">仓库</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">电子邮箱</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">邮箱地址</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT配置</x:String>
@ -255,6 +264,8 @@
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目标 </x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">编辑分组</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">编辑仓库</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">执行自定义操作</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">自定义操作 </x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快进(fast-forward无需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">拉取所有的远程仓库</x:String>
@ -519,6 +530,8 @@
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">自定义操作</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">自定义操作未设置</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">启用 --reflog 选项</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速查找分支/标签/子模块</x:String>

View file

@ -111,6 +111,7 @@
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">與本機工作區比較</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">複製摘要資訊</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">複製提交編號</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">自訂動作</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">互動式重定基底 (rebase -i) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 到此處</x:String>
<x:String x:Key="Text.CommitCM.Reset" xml:space="preserve">重設 (reset) ${0}$ 到此處</x:String>
@ -142,6 +143,14 @@
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">提交訊息範本</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Name" xml:space="preserve">範本名稱:</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate.Content" xml:space="preserve">範本內容:</x:String>
<x:String x:Key="Text.Configure.CustomAction" xml:space="preserve">自訂動作</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments" xml:space="preserve">指令行參數:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Arguments.Tip" xml:space="preserve">使用${REPO}代表儲存庫的路徑,${SHA}代表所選的提交編號</x:String>
<x:String x:Key="Text.Configure.CustomAction.Executable" xml:space="preserve">可執行檔案路徑:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Name" xml:space="preserve">名稱 </x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope" xml:space="preserve">執行範圍:</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">選取的提交</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">存放庫</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">電子郵件</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">電子郵件地址</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">Git 設定</x:String>
@ -255,6 +264,8 @@
<x:String x:Key="Text.EditRepositoryNode.Target" xml:space="preserve">目標:</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForGroup" xml:space="preserve">編輯群組</x:String>
<x:String x:Key="Text.EditRepositoryNode.TitleForRepository" xml:space="preserve">編輯存放庫</x:String>
<x:String x:Key="Text.ExecuteCustomAction" xml:space="preserve">執行自訂動作</x:String>
<x:String x:Key="Text.ExecuteCustomAction.Name" xml:space="preserve">自訂動作:</x:String>
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快進 (fast-forward無需 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">提取所有的遠端存放庫</x:String>
@ -519,6 +530,8 @@
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String>
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">設定本存放庫</x:String>
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
<x:String x:Key="Text.Repository.CustomActions" xml:space="preserve">自訂動作</x:String>
<x:String x:Key="Text.Repository.CustomActions.Empty" xml:space="preserve">沒有自訂的動作</x:String>
<x:String x:Key="Text.Repository.EnableReflog" xml:space="preserve">啟用 [--reflog] 選項</x:String>
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在檔案瀏覽器中開啟</x:String>
<x:String x:Key="Text.Repository.Filter" xml:space="preserve">快速搜尋分支/標籤/子模組</x:String>

View file

@ -83,7 +83,7 @@
<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">fonts:Inter#Inter, $Default</FontFamily>
<FontFamily x:Key="Fonts.Default">fonts:Inter#Inter</FontFamily>
<FontFamily x:Key="Fonts.Monospace">fonts:SourceGit#JetBrains Mono</FontFamily>
<FontFamily x:Key="Fonts.Primary">fonts:SourceGit#JetBrains Mono</FontFamily>
</ResourceDictionary>

View file

@ -0,0 +1,40 @@
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
public class ExecuteCustomAction : Popup
{
public Models.CustomAction CustomAction
{
get;
private set;
}
public ExecuteCustomAction(Repository repo, Models.CustomAction action, Models.Commit commit)
{
_repo = repo;
_args = action.Arguments.Replace("${REPO}", _repo.FullPath);
if (commit != null)
_args = _args.Replace("${SHA}", commit.SHA);
CustomAction = action;
View = new Views.ExecuteCustomAction() { DataContext = this };
}
public override Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = "Run custom action ...";
return Task.Run(() =>
{
Commands.ExecuteCustomAction.Run(_repo.FullPath, CustomAction.Executable, _args, SetProgressDescription);
CallUIThread(() => _repo.SetWatcherEnabled(true));
return true;
});
}
private readonly Repository _repo = null;
private string _args = string.Empty;
}
}

View file

@ -605,6 +605,39 @@ namespace SourceGit.ViewModels
menu.Items.Add(archive);
menu.Items.Add(new MenuItem() { Header = "-" });
var actions = new List<Models.CustomAction>();
foreach (var action in _repo.Settings.CustomActions)
{
if (action.Scope == Models.CustomActionScope.Commit)
actions.Add(action);
}
if (actions.Count > 0)
{
var custom = new MenuItem();
custom.Header = App.Text("CommitCM.CustomAction");
custom.Icon = App.CreateMenuIcon("Icons.Action");
foreach (var action in actions)
{
var dup = action;
var item = new MenuItem();
item.Icon = App.CreateMenuIcon("Icons.Action");
item.Header = dup.Name;
item.Click += (_, e) =>
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new ExecuteCustomAction(_repo, dup, commit));
e.Handled = true;
};
custom.Items.Add(item);
}
menu.Items.Add(custom);
menu.Items.Add(new MenuItem() { Header = "-" });
}
var copySHA = new MenuItem();
copySHA.Header = App.Text("CommitCM.CopySHA");
copySHA.Icon = App.CreateMenuIcon("Icons.Copy");

View file

@ -1287,6 +1287,45 @@ namespace SourceGit.ViewModels
return menu;
}
public ContextMenu CreateContextMenuForCustomAction()
{
var actions = new List<Models.CustomAction>();
foreach (var action in _settings.CustomActions)
{
if (action.Scope == Models.CustomActionScope.Repository)
actions.Add(action);
}
var menu = new ContextMenu();
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
if (actions.Count > 0)
{
foreach (var action in actions)
{
var dup = action;
var item = new MenuItem();
item.Icon = App.CreateMenuIcon("Icons.Action");
item.Header = dup.Name;
item.Click += (_, e) =>
{
if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new ExecuteCustomAction(this, dup, null));
e.Handled = true;
};
menu.Items.Add(item);
}
}
else
{
menu.Items.Add(new MenuItem() { Header = App.Text("Repository.CustomActions.Empty") });
}
return menu;
}
public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
{
var menu = new ContextMenu();

View file

@ -127,6 +127,17 @@ namespace SourceGit.ViewModels
set => _repo.Settings.PreferedOpenAIService = value;
}
public AvaloniaList<Models.CustomAction> CustomActions
{
get => _repo.Settings.CustomActions;
}
public Models.CustomAction SelectedCustomAction
{
get => _selectedCustomAction;
set => SetProperty(ref _selectedCustomAction, value);
}
public RepositoryConfigure(Repository repo)
{
_repo = repo;
@ -233,11 +244,21 @@ namespace SourceGit.ViewModels
public void RemoveSelectedIssueTracker()
{
if (_selectedIssueTrackerRule != null)
_repo.Settings.RemoveIssueTracker(_selectedIssueTrackerRule);
_repo.Settings.RemoveIssueTracker(_selectedIssueTrackerRule);
SelectedIssueTrackerRule = null;
}
public void AddNewCustomAction()
{
SelectedCustomAction = _repo.Settings.AddNewCustomAction();
}
public void RemoveSelectedCustomAction()
{
_repo.Settings.RemoveCustomAction(_selectedCustomAction);
SelectedCustomAction = null;
}
public void Save()
{
SetIfChanged("user.name", UserName, "");
@ -271,5 +292,6 @@ namespace SourceGit.ViewModels
private string _httpProxy;
private Models.CommitTemplate _selectedCommitTemplate = null;
private Models.IssueTrackerRule _selectedIssueTrackerRule = null;
private Models.CustomAction _selectedCustomAction = null;
}
}

View file

@ -15,30 +15,23 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.AIAssist}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.AIAssistant}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -4,7 +4,6 @@ using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Threading;
namespace SourceGit.Views
@ -55,11 +54,6 @@ namespace SourceGit.Views
_cancel.Cancel();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void SetDescription(string message)
{
Dispatcher.UIThread.Invoke(() => ProgressMessage.Text = message);

View file

@ -13,30 +13,23 @@
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Info}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.About}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -21,11 +21,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void OnVisitAvaloniaUI(object _, PointerPressedEventArgs e)
{
Native.OS.OpenBrowser("https://www.avaloniaui.net/");

View file

@ -13,30 +13,23 @@
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,*">
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Password}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.Askpass}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,7 +1,6 @@
using System;
using Avalonia;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
@ -42,11 +41,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2)
{
Console.Out.WriteLine("No passphrase entered.");

View file

@ -16,30 +16,23 @@
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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.File.Ignore}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.AssumeUnchanged}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,5 +1,4 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
@ -11,11 +10,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void OnRemoveButtonClicked(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.AssumeUnchangedManager vm && sender is Button button)

View file

@ -19,29 +19,26 @@
</Grid.RowDefinitions>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="4"
Background="{DynamicResource Brush.TitleBar}"
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) -->
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}">
<v:CaptionButtonsMacOS/>
</Border>
<!-- Icon -->
<Path Grid.Column="1" Margin="8,0,0,0" Width="12" Height="12" Data="{StaticResource Icons.Blame}"/>
<!-- Title -->
<TextBlock Grid.Column="2" Margin="8,0,0,0" Text="{DynamicResource Text.Blame}" FontWeight="Bold" IsHitTestVisible="False" VerticalAlignment="Center"/>
<Path Width="12" Height="12"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Blame}"
IsVisible="{OnPlatform True, macOS=False}"/>
<TextBlock Classes="bold"
Text="{DynamicResource Text.Blame}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<!-- Caption Buttons (Windows/Linux) -->
<Border Grid.Column="3" IsVisible="{OnPlatform True, macOS=False}">
<v:CaptionButtons/>
</Border>
<v:CaptionButtons HorizontalAlignment="Right" IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>
<!-- File -->

View file

@ -435,24 +435,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void MaximizeOrRestoreWindow(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);

View file

@ -21,29 +21,26 @@
</Grid.RowDefinitions>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="4"
Background="{DynamicResource Brush.TitleBar}"
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) -->
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}">
<v:CaptionButtonsMacOS/>
</Border>
<!-- Icon -->
<Path Grid.Column="1" Margin="8,0,0,0" Width="12" Height="12" Data="{StaticResource Icons.Compare}"/>
<!-- Title -->
<TextBlock Grid.Column="2" Margin="8,0,0,0" Text="{DynamicResource Text.BranchCompare}" FontWeight="Bold" IsHitTestVisible="False" VerticalAlignment="Center"/>
<Path Width="12" Height="12"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Compare}"
IsVisible="{OnPlatform True, macOS=False}"/>
<TextBlock Classes="bold"
Text="{DynamicResource Text.BranchCompare}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<!-- Caption Buttons (Windows/Linux) -->
<Border Grid.Column="3" IsVisible="{OnPlatform True, macOS=False}">
<v:CaptionButtons/>
</Border>
<v:CaptionButtons HorizontalAlignment="Right" IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>
<!-- Compare Targets -->

View file

@ -10,24 +10,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void MaximizeOrRestoreWindow(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e)
{
if (DataContext is ViewModels.BranchCompare vm && sender is ChangeCollectionView view)

View file

@ -1,159 +0,0 @@
<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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.CaptionButtonsMacOS"
x:Name="ThisControl">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<Color x:Key="Color.MacOS.Close">#FFED6A5E</Color>
<Color x:Key="Color.MacOS.CloseFG">#FF69110A</Color>
<Color x:Key="Color.MacOS.ClosePressed">#FFB24F46</Color>
<Color x:Key="Color.MacOS.ClosePressedFG">#FF2E0402</Color>
<Color x:Key="Color.MacOS.Minimize">#FFF4BF4F</Color>
<Color x:Key="Color.MacOS.MinimizeFG">#FF8F591D</Color>
<Color x:Key="Color.MacOS.MinimizePressed">#FFB78F3A</Color>
<Color x:Key="Color.MacOS.MinimizePressedFG">#FF522A0A</Color>
<Color x:Key="Color.MacOS.Maximize">#FF61C554</Color>
<Color x:Key="Color.MacOS.MaximizeFG">#FF296017</Color>
<Color x:Key="Color.MacOS.MaximizePressed">#FF48943F</Color>
<Color x:Key="Color.MacOS.MaximizePressedFG">#FF102F07</Color>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<Color x:Key="Color.MacOS.Close">#FFED6A5E</Color>
<Color x:Key="Color.MacOS.CloseFG">#FF8C1A10</Color>
<Color x:Key="Color.MacOS.ClosePressed">#FFF09389</Color>
<Color x:Key="Color.MacOS.ClosePressedFG">#FF69120A</Color>
<Color x:Key="Color.MacOS.Minimize">#FFF4BF4F</Color>
<Color x:Key="Color.MacOS.MinimizeFG">#FF8F591D</Color>
<Color x:Key="Color.MacOS.MinimizePressed">#FFFBEB74</Color>
<Color x:Key="Color.MacOS.MinimizePressedFG">#FF705F1B</Color>
<Color x:Key="Color.MacOS.Maximize">#FF61C554</Color>
<Color x:Key="Color.MacOS.MaximizeFG">#FF296017</Color>
<Color x:Key="Color.MacOS.MaximizePressed">#FF86F37F</Color>
<Color x:Key="Color.MacOS.MaximizePressedFG">#FF2C681A</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<SolidColorBrush x:Key="Brush.MacOS.Close" Color="{DynamicResource Color.MacOS.Close}"/>
<SolidColorBrush x:Key="Brush.MacOS.CloseFG" Color="{DynamicResource Color.MacOS.CloseFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.ClosePressed" Color="{DynamicResource Color.MacOS.ClosePressed}"/>
<SolidColorBrush x:Key="Brush.MacOS.ClosePressedFG" Color="{DynamicResource Color.MacOS.ClosePressedFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.Minimize" Color="{DynamicResource Color.MacOS.Minimize}"/>
<SolidColorBrush x:Key="Brush.MacOS.MinimizeFG" Color="{DynamicResource Color.MacOS.MinimizeFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.MinimizePressed" Color="{DynamicResource Color.MacOS.MinimizePressed}"/>
<SolidColorBrush x:Key="Brush.MacOS.MinimizePressedFG" Color="{DynamicResource Color.MacOS.MinimizePressedFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.Maximize" Color="{DynamicResource Color.MacOS.Maximize}"/>
<SolidColorBrush x:Key="Brush.MacOS.MaximizeFG" Color="{DynamicResource Color.MacOS.MaximizeFG}"/>
<SolidColorBrush x:Key="Brush.MacOS.MaximizePressed" Color="{DynamicResource Color.MacOS.MaximizePressed}"/>
<SolidColorBrush x:Key="Brush.MacOS.MaximizePressedFG" Color="{DynamicResource Color.MacOS.MaximizePressedFG}"/>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="Width" Value="24"/>
<Setter Property="Height" Value="24"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style Selector="Button /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="Button>Grid>Ellipse">
<Setter Property="Width" Value="14"/>
<Setter Property="Height" Value="14"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="StrokeThickness" Value=".5"/>
<Setter Property="Stroke" Value="#40000000"/>
</Style>
<Style Selector="Button.close>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.Close}"/>
</Style>
<Style Selector="Button.minimize>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.Minimize}"/>
</Style>
<Style Selector="Button.maximize>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.Maximize}"/>
</Style>
<Style Selector="Button.close:pressed>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.ClosePressed}"/>
</Style>
<Style Selector="Button.minimize:pressed>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MinimizePressed}"/>
</Style>
<Style Selector="Button.maximize:pressed>Grid>Ellipse">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MaximizePressed}"/>
</Style>
<Style Selector="Button>Grid>Path">
<Setter Property="Stretch" Value="Fill"/>
<Setter Property="Fill" Value="Black"/>
<Setter Property="IsVisible" Value="False"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style Selector="Button.close>Grid>Path">
<Setter Property="Width" Value="6"/>
<Setter Property="Height" Value="6"/>
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.CloseFG}"/>
<Setter Property="Data" Value="{StaticResource Icons.MacOS.Close}"/>
</Style>
<Style Selector="Button.minimize>Grid>Path">
<Setter Property="Width" Value="8"/>
<Setter Property="Height" Value="2"/>
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MinimizeFG}"/>
<Setter Property="Data" Value="{StaticResource Icons.MacOS.Minimize}"/>
</Style>
<Style Selector="Button.maximize>Grid>Path">
<Setter Property="Width" Value="6"/>
<Setter Property="Height" Value="6"/>
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MaximizeFG}"/>
<Setter Property="Data" Value="{StaticResource Icons.MacOS.Maximize}"/>
</Style>
<Style Selector="Button.close:pressed>Grid>Path">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.ClosePressedFG}"/>
</Style>
<Style Selector="Button.minimize:pressed>Grid>Path">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MinimizePressedFG}"/>
</Style>
<Style Selector="Button.maximize:pressed>Grid>Path">
<Setter Property="Fill" Value="{DynamicResource Brush.MacOS.MaximizePressedFG}"/>
</Style>
<Style Selector="Grid.caption_button_box:pointerover>StackPanel>Button>Grid>Path">
<Setter Property="IsVisible" Value="True"/>
</Style>
</UserControl.Styles>
<Grid Classes="caption_button_box">
<StackPanel Orientation="Horizontal" Margin="8,0,0,0">
<Button Classes="close" Click="CloseWindow">
<Grid>
<Ellipse/>
<Path/>
</Grid>
</Button>
<Button Classes="minimize" Click="MinimizeWindow" IsVisible="{Binding !#ThisControl.IsCloseButtonOnly}">
<Grid>
<Ellipse/>
<Path/>
</Grid>
</Button>
<Button Classes="maximize" Click="MaximizeOrRestoreWindow" IsVisible="{Binding !#ThisControl.IsCloseButtonOnly}">
<Grid>
<Ellipse/>
<Path/>
</Grid>
</Button>
</StackPanel>
</Grid>
</UserControl>

View file

@ -1,49 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
namespace SourceGit.Views
{
public partial class CaptionButtonsMacOS : UserControl
{
public static readonly StyledProperty<bool> IsCloseButtonOnlyProperty =
AvaloniaProperty.Register<CaptionButtonsMacOS, bool>(nameof(IsCloseButtonOnly));
public bool IsCloseButtonOnly
{
get => GetValue(IsCloseButtonOnlyProperty);
set => SetValue(IsCloseButtonOnlyProperty, value);
}
public CaptionButtonsMacOS()
{
InitializeComponent();
}
private void MinimizeWindow(object _, RoutedEventArgs e)
{
var window = this.FindAncestorOfType<Window>();
if (window != null)
window.WindowState = WindowState.Minimized;
e.Handled = true;
}
private void MaximizeOrRestoreWindow(object _, RoutedEventArgs e)
{
var window = this.FindAncestorOfType<Window>();
if (window != null)
window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
e.Handled = true;
}
private void CloseWindow(object _, RoutedEventArgs e)
{
var window = this.FindAncestorOfType<Window>();
window?.Close();
e.Handled = true;
}
}
}

View file

@ -32,14 +32,35 @@ namespace SourceGit.Views
Classes.Add("custom_window_frame");
}
}
else
else if (OperatingSystem.IsWindows())
{
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome;
ExtendClientAreaToDecorationsHint = true;
if (OperatingSystem.IsWindows())
Classes.Add("fix_maximized_padding");
Classes.Add("fix_maximized_padding");
}
else
{
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome;
ExtendClientAreaToDecorationsHint = true;
}
}
public void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
public void MaximizeOrRestoreWindow(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)

View file

@ -2,10 +2,8 @@
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"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.ConfigureWorkspace"
x:DataType="vm:ConfigureWorkspace"
@ -17,30 +15,23 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto" MinWidth="494">
<!-- 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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
Data="{StaticResource Icons.Workspace}"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Workspace}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.ConfigureWorkspace}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,5 +1,4 @@
using Avalonia.Controls;
using Avalonia.Input;
namespace SourceGit.Views
{
@ -15,10 +14,5 @@ namespace SourceGit.Views
ViewModels.Preference.Instance.Save();
base.OnClosing(e);
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
}
}

View file

@ -15,30 +15,23 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
Data="{StaticResource Icons.Error}"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Error}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.Warn}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,4 +1,3 @@
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
@ -10,11 +9,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void Sure(object _1, RoutedEventArgs _2)
{
if (DataContext is ViewModels.ConfirmCommitWithoutFiles vm)

View file

@ -13,30 +13,23 @@
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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Info}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="Restart Required"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,8 +1,6 @@
using System;
using System.Diagnostics;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
@ -14,11 +12,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2)
{
Console.Out.WriteLine("No passphrase entered.");

View file

@ -5,7 +5,6 @@
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.ConventionalCommitMessageBuilder"
x:DataType="vm:ConventionalCommitMessageBuilder"
@ -18,30 +17,23 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
Data="{StaticResource Icons.CommitMessageGenerator}"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.CommitMessageGenerator}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.ConventionalCommit}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,4 +1,3 @@
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
@ -10,11 +9,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void OnApplyClicked(object _, RoutedEventArgs e)
{
if (DataContext is ViewModels.ConventionalCommitMessageBuilder builder)

View file

@ -0,0 +1,19 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:SourceGit.ViewModels"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="SourceGit.Views.ExecuteCustomAction"
x:DataType="vm:ExecuteCustomAction">
<StackPanel Orientation="Vertical" Margin="8,0">
<TextBlock FontSize="18"
Classes="bold"
Text="{DynamicResource Text.ExecuteCustomAction}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,16,0,0">
<TextBlock Text="{DynamicResource Text.ExecuteCustomAction.Name}"/>
<Path Width="14" Height="14" Margin="8,0,0,0" Data="{StaticResource Icons.Action}"/>
<TextBlock Text="{Binding CustomAction.Name}" Margin="8,0,0,0"/>
</StackPanel>
</StackPanel>
</UserControl>

View file

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

View file

@ -20,29 +20,26 @@
</Grid.RowDefinitions>
<!-- TitleBar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border -->
<Border Grid.Column="0" Grid.ColumnSpan="4"
Background="{DynamicResource Brush.TitleBar}"
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) -->
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}">
<v:CaptionButtonsMacOS/>
</Border>
<!-- Icon -->
<Path Grid.Column="1" Margin="8,0,0,0" Width="12" Height="12" Stretch="Uniform" Data="{StaticResource Icons.Histories}"/>
<!-- Title -->
<TextBlock Grid.Column="2" Margin="4,0,0,0" Text="{DynamicResource Text.FileHistory}" FontWeight="Bold" IsHitTestVisible="False" VerticalAlignment="Center"/>
<Path Width="12" Height="12"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Histories}"
IsVisible="{OnPlatform True, macOS=False}"/>
<TextBlock Classes="bold"
Text="{DynamicResource Text.FileHistory}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<!-- Caption Buttons (Windows/Linux) -->
<Border Grid.Column="3" IsVisible="{OnPlatform True, macOS=False}">
<v:CaptionButtons/>
</Border>
<v:CaptionButtons HorizontalAlignment="Right" IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>
<!-- Body -->

View file

@ -11,24 +11,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void MaximizeOrRestoreWindow(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
private void OnPressCommitSHA(object sender, PointerPressedEventArgs e)
{
if (sender is TextBlock { DataContext: Models.Commit commit } &&

View file

@ -15,30 +15,23 @@
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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Hotkeys}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.Hotkeys}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,5 +1,3 @@
using Avalonia.Input;
namespace SourceGit.Views
{
public partial class Hotkeys : ChromelessWindow
@ -8,10 +6,5 @@ namespace SourceGit.Views
{
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
}
}

View file

@ -16,30 +16,23 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,*,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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.InteractiveRebase}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.InteractiveRebase}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -81,11 +81,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2)
{
Close();

View file

@ -16,30 +16,23 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Lock}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.GitLFS.Locks.Title}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,5 +1,4 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
@ -11,11 +10,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void OnUnlockButtonClicked(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.LFSLocks vm && sender is Button button)

View file

@ -25,13 +25,11 @@
<Border Grid.Column="0" Grid.ColumnSpan="4"
Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
DoubleTapped="OnTitleBarDoubleTapped"
DoubleTapped="MaximizeOrRestoreWindow"
PointerPressed="BeginMoveWindow"/>
<!-- Caption Buttons (macOS) -->
<Border Grid.Column="0" VerticalAlignment="Stretch" Margin="2,0,8,3" IsVisible="{OnPlatform False, macOS=True}">
<v:CaptionButtonsMacOS VerticalAlignment="Bottom"/>
</Border>
<Border Grid.Column="0" Width="72" IsVisible="{Binding #ThisControl.HasLeftCaptionButton}"/>
<!-- Menu (Windows/Linux) -->
<Button Grid.Column="0" Classes="icon_button" VerticalAlignment="Bottom" Margin="6,0,2,3" IsVisible="{OnPlatform True, macOS=False}">

View file

@ -4,6 +4,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Platform;
using Avalonia.VisualTree;
namespace SourceGit.Views
@ -19,6 +20,15 @@ namespace SourceGit.Views
set => SetValue(CaptionHeightProperty, value);
}
public static readonly StyledProperty<bool> HasLeftCaptionButtonProperty =
AvaloniaProperty.Register<Launcher, bool>(nameof(HasLeftCaptionButton));
public bool HasLeftCaptionButton
{
get => GetValue(HasLeftCaptionButtonProperty);
set => SetValue(HasLeftCaptionButtonProperty, value);
}
public bool IsRightCaptionButtonsVisible
{
get
@ -38,10 +48,21 @@ namespace SourceGit.Views
Height = layout.LauncherHeight;
}
if (UseSystemWindowFrame)
if (OperatingSystem.IsMacOS())
{
HasLeftCaptionButton = true;
CaptionHeight = new GridLength(34);
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.SystemChrome |
ExtendClientAreaChromeHints.OSXThickTitleBar;
}
else if (UseSystemWindowFrame)
{
CaptionHeight = new GridLength(30);
}
else
{
CaptionHeight = new GridLength(38);
}
InitializeComponent();
}
@ -55,8 +76,8 @@ namespace SourceGit.Views
{
base.OnOpened(e);
var layout = ViewModels.Preference.Instance.Layout;
if (layout.LauncherWindowState == WindowState.Maximized)
var state = ViewModels.Preference.Instance.Layout.LauncherWindowState;
if (state == WindowState.Maximized || state == WindowState.FullScreen)
WindowState = WindowState.Maximized;
}
@ -67,12 +88,11 @@ namespace SourceGit.Views
if (change.Property == WindowStateProperty)
{
var state = (WindowState)change.NewValue!;
if (OperatingSystem.IsLinux() && UseSystemWindowFrame)
CaptionHeight = new GridLength(30);
else if (state == WindowState.Maximized)
CaptionHeight = new GridLength(OperatingSystem.IsMacOS() ? 34 : 30);
else
CaptionHeight = new GridLength(38);
if (!OperatingSystem.IsMacOS() && !UseSystemWindowFrame)
CaptionHeight = new GridLength(state == WindowState.Maximized ? 30 : 38);
if (OperatingSystem.IsMacOS())
HasLeftCaptionButton = state != WindowState.FullScreen;
ViewModels.Preference.Instance.Layout.LauncherWindowState = state;
}
@ -225,24 +245,6 @@ namespace SourceGit.Views
base.OnClosing(e);
}
private void OnTitleBarDoubleTapped(object _, TappedEventArgs e)
{
if (WindowState == WindowState.Maximized)
WindowState = WindowState.Normal;
else
WindowState = WindowState.Maximized;
e.Handled = true;
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
if (e.ClickCount == 1)
BeginMoveDrag(e);
e.Handled = true;
}
private void OnOpenWorkspaceMenu(object sender, RoutedEventArgs e)
{
if (sender is Button btn && DataContext is ViewModels.Launcher launcher)

View file

@ -17,30 +17,23 @@
WindowStartupLocation="CenterScreen">
<Grid RowDefinitions="Auto,Auto" MinWidth="600">
<!-- 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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
Data="{StaticResource Icons.Settings}"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Settings}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.Preference}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
@ -166,11 +165,6 @@ namespace SourceGit.Views
base.OnClosing(e);
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private async void SelectThemeOverrideFile(object _, RoutedEventArgs e)
{
var options = new FilePickerOpenOptions()

View file

@ -5,6 +5,7 @@
xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views"
xmlns:ac="using:Avalonia.Controls.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.RepositoryConfigure"
x:DataType="vm:RepositoryConfigure"
@ -16,30 +17,23 @@
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
Data="{StaticResource Icons.Settings}"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Settings}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.Configure}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>
@ -345,6 +339,116 @@
</Grid>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.CustomAction}"/>
</TabItem.Header>
<Grid ColumnDefinitions="200,*" Height="250" Margin="0,8,0,16">
<Border Grid.Column="0"
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
Background="{DynamicResource Brush.Contents}">
<Grid RowDefinitions="*,1,Auto">
<ListBox Grid.Row="0"
Background="Transparent"
ItemsSource="{Binding CustomActions}"
SelectedItem="{Binding SelectedCustomAction, Mode=TwoWay}"
SelectionMode="Single">
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Height" Value="26"/>
<Setter Property="Padding" Value="4,2"/>
</Style>
</ListBox.Styles>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate DataType="m:CustomAction">
<Grid Margin="4,0" ColumnDefinitions="Auto,*">
<Path Grid.Column="0" Width="12" Height="12" Data="{StaticResource Icons.Action}" Fill="{DynamicResource Brush.FG1}"/>
<TextBlock Grid.Column="1" Text="{Binding Name}" Margin="6,0,0,0" TextTrimming="CharacterEllipsis"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Rectangle Grid.Row="1" Height="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"/>
<StackPanel Grid.Row="2" Orientation="Horizontal" Background="{DynamicResource Brush.ToolBar}">
<Button Classes="icon_button" Command="{Binding AddNewCustomAction}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Plus}"/>
</Button>
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
<Button Classes="icon_button" Command="{Binding RemoveSelectedCustomAction}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Window.Minimize}"/>
</Button>
<Rectangle Width="1" Fill="{DynamicResource Brush.Border2}" HorizontalAlignment="Left" VerticalAlignment="Stretch"/>
</StackPanel>
</Grid>
</Border>
<ContentControl Grid.Column="1" Margin="16,0,0,0">
<ContentControl.Content>
<Binding Path="SelectedCustomAction">
<Binding.TargetNullValue>
<Path Width="64" Height="64"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{DynamicResource Brush.FG2}"
Data="{StaticResource Icons.Empty}"/>
</Binding.TargetNullValue>
</Binding>
</ContentControl.Content>
<ContentControl.DataTemplates>
<DataTemplate DataType="m:CustomAction">
<StackPanel Orientation="Vertical">
<TextBlock Text="{DynamicResource Text.Configure.CustomAction.Name}"/>
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Name, Mode=TwoWay}"/>
<StackPanel Orientation="Horizontal" Margin="0,12,0,0">
<StackPanel.Resources>
<ac:EnumToBoolConverter x:Key="EnumToBoolConverter"/>
</StackPanel.Resources>
<TextBlock Text="{DynamicResource Text.Configure.CustomAction.Scope}"/>
<RadioButton Content="{DynamicResource Text.Configure.CustomAction.Scope.Repository}"
GroupName="CustomActionScope"
Margin="8,0"
IsChecked="{Binding Scope, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:CustomActionScope.Repository}}"/>
<RadioButton Content="{DynamicResource Text.Configure.CustomAction.Scope.Commit}"
GroupName="CustomActionScope"
IsChecked="{Binding Scope, Mode=TwoWay, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static m:CustomActionScope.Commit}}"/>
</StackPanel>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CustomAction.Executable}"/>
<TextBox Margin="0,4,0,0" Height="28" CornerRadius="3" Text="{Binding Executable, Mode=TwoWay}">
<TextBox.InnerRightContent>
<Button Classes="icon_button" Width="30" Height="30" Click="SelectExecutableForCustomAction">
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
</Button>
</TextBox.InnerRightContent>
</TextBox>
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Configure.CustomAction.Arguments}"/>
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Arguments, Mode=TwoWay}"/>
<TextBlock Margin="0,2,0,0" TextWrapping="Wrap" Text="{DynamicResource Text.Configure.CustomAction.Arguments.Tip}" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel>
</DataTemplate>
</ContentControl.DataTemplates>
</ContentControl>
</Grid>
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Configure.OpenAI}"/>

View file

@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
namespace SourceGit.Views
{
@ -16,9 +17,19 @@ namespace SourceGit.Views
base.OnClosing(e);
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
private async void SelectExecutableForCustomAction(object sender, RoutedEventArgs e)
{
BeginMoveDrag(e);
var options = new FilePickerOpenOptions()
{
FileTypeFilter = [new FilePickerFileType("Executable file(script)") { Patterns = ["*.*"] }],
AllowMultiple = false,
};
var selected = await StorageProvider.OpenFilePickerAsync(options);
if (selected.Count == 1 && sender is Button { DataContext: Models.CustomAction action })
action.Executable = selected[0].Path.LocalPath;
e.Handled = true;
}
}
}

View file

@ -96,6 +96,10 @@
<Path Width="14" Height="14" Data="{StaticResource Icons.LFS}"/>
</Button>
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Click="OpenCustomActionMenu" ToolTip.Tip="{DynamicResource Text.Repository.CustomActions}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Action}"/>
</Button>
<Button Classes="icon_button" Width="32" Margin="8,0,0,0" Command="{Binding Cleanup}" ToolTip.Tip="{DynamicResource Text.Repository.Clean}">
<Path Width="14" Height="14" Margin="0,1,0,0" Data="{StaticResource Icons.Clean}"/>
</Button>

View file

@ -91,6 +91,17 @@ namespace SourceGit.Views
e.Handled = true;
}
private void OpenCustomActionMenu(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForCustomAction();
(sender as Control)?.OpenContextMenu(menu);
}
e.Handled = true;
}
}
}

View file

@ -17,30 +17,23 @@
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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.SoftwareUpdate}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.SelfUpdate.Title}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,5 +1,4 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
@ -11,11 +10,6 @@ namespace SourceGit.Views
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void CloseWindow(object _1, RoutedEventArgs _2)
{
Close();

View file

@ -14,30 +14,23 @@
WindowStartupLocation="CenterScreen">
<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}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Edit}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.CodeEditor}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,7 +1,6 @@
using System;
using System.IO;
using Avalonia.Input;
using Avalonia.Interactivity;
namespace SourceGit.Views
@ -40,11 +39,6 @@ namespace SourceGit.Views
App.Quit(_exitCode);
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
private void SaveAndClose(object _1, RoutedEventArgs _2)
{
File.WriteAllText(_file, Editor.Text);

View file

@ -16,30 +16,23 @@
CanResize="False">
<Grid RowDefinitions="Auto,Auto,*">
<!-- Title bar -->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Grid.Column="0" Grid.ColumnSpan="3"
Background="{DynamicResource Brush.TitleBar}"
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
PointerPressed="BeginMoveWindow"/>
<Path Grid.Column="0"
Width="14" Height="14"
<Path Width="14" Height="14"
Margin="10,0,0,0"
HorizontalAlignment="Left"
Data="{StaticResource Icons.Statistics}"
IsVisible="{OnPlatform True, macOS=False}"/>
<v:CaptionButtonsMacOS Grid.Column="0"
Margin="0,2,0,0"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform False, macOS=True}"/>
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
Classes="bold"
<TextBlock Classes="bold"
Text="{DynamicResource Text.Statistics}"
HorizontalAlignment="Center" VerticalAlignment="Center"
IsHitTestVisible="False"/>
<v:CaptionButtons Grid.Column="2"
<v:CaptionButtons HorizontalAlignment="Right"
IsCloseButtonOnly="True"
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>

View file

@ -1,5 +1,3 @@
using Avalonia.Input;
namespace SourceGit.Views
{
public partial class Statistics : ChromelessWindow
@ -8,10 +6,5 @@ namespace SourceGit.Views
{
InitializeComponent();
}
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
{
BeginMoveDrag(e);
}
}
}