Skip to content

Commit 9153bbe

Browse files
committed
feature: add conventional commit message generator (#574)
1 parent 2821bab commit 9153bbe

10 files changed

+369
-8
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Collections.Generic;
2+
3+
namespace SourceGit.Models
4+
{
5+
public class ConventionalCommitType
6+
{
7+
public string Type { get; set; } = string.Empty;
8+
public string Description { get; set; } = string.Empty;
9+
10+
public static readonly List<ConventionalCommitType> Supported = new List<ConventionalCommitType>()
11+
{
12+
new ConventionalCommitType("feat", "Adding a new feature"),
13+
new ConventionalCommitType("fix", "Fixing a bug"),
14+
new ConventionalCommitType("docs", "Updating documentation"),
15+
new ConventionalCommitType("style", "Elements or code styles without changing the code logic"),
16+
new ConventionalCommitType("test", "Adding or updating tests"),
17+
new ConventionalCommitType("chore", "Making changes to the build process or auxiliary tools and libraries"),
18+
new ConventionalCommitType("revert", "Undoing a previous commit"),
19+
new ConventionalCommitType("refactor", "Restructuring code without changing its external behavior")
20+
};
21+
22+
public ConventionalCommitType(string type, string description)
23+
{
24+
Type = type;
25+
Description = description;
26+
}
27+
}
28+
}

src/Resources/Icons.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<StreamGeometry x:Key="Icons.Code">M853 102H171C133 102 102 133 102 171v683C102 891 133 922 171 922h683C891 922 922 891 922 853V171C922 133 891 102 853 102zM390 600l-48 48L205 512l137-137 48 48L301 512l88 88zM465 819l-66-18L559 205l66 18L465 819zm218-171L634 600 723 512l-88-88 48-48L819 512 683 649z</StreamGeometry>
1717
<StreamGeometry x:Key="Icons.ColorPicker">M128 854h768v86H128zM390 797c13 13 29 19 48 19s35-6 45-19l291-288c26-22 26-64 0-90L435 83l-61 61L426 192l-272 269c-22 22-22 64 0 90l237 246zm93-544 211 211-32 32H240l243-243zM707 694c0 48 38 86 86 86 48 0 86-38 86-86 0-22-10-45-26-61L794 576l-61 61c-13 13-26 35-26 58z</StreamGeometry>
1818
<StreamGeometry x:Key="Icons.Commit">M796 471A292 292 0 00512 256a293 293 0 00-284 215H0v144h228A293 293 0 00512 832a291 291 0 00284-217H1024V471h-228M512 688A146 146 0 01366 544A145 145 0 01512 400c80 0 146 63 146 144A146 146 0 01512 688</StreamGeometry>
19+
<StreamGeometry x:Key="Icons.CommitMessageGenerator">M796 561a5 5 0 014 7l-39 90a5 5 0 004 7h100a5 5 0 014 8l-178 247a5 5 0 01-9-4l32-148a5 5 0 00-5-6h-89a5 5 0 01-4-7l86-191a5 5 0 014-3h88zM731 122a73 73 0 0173 73v318a54 54 0 00-8-1H731V195H244v634h408l-16 73H244a73 73 0 01-73-73V195a73 73 0 0173-73h488zm-219 366v73h-195v-73h195zm146-146v73H317v-73h341z</StreamGeometry>
1920
<StreamGeometry x:Key="Icons.Compare">M645 448l64 64 220-221L704 64l-64 64 115 115H128v90h628zM375 576l-64-64-220 224L314 960l64-64-116-115H896v-90H262z</StreamGeometry>
2021
<StreamGeometry x:Key="Icons.Conflict">M608 0q48 0 88 23t63 63 23 87v70h55q35 0 67 14t57 38 38 57 14 67V831q0 34-14 66t-38 57-57 38-67 13H426q-34 0-66-13t-57-38-38-57-14-66v-70h-56q-34 0-66-14t-57-38-38-57-13-67V174q0-47 23-87T109 23 196 0h412m175 244H426q-46 0-86 22T278 328t-26 85v348H608q47 0 86-22t63-62 25-85l1-348m-269 318q18 0 31 13t13 31-13 31-31 13-31-13-13-31 13-31 31-13m0-212q13 0 22 9t11 22v125q0 14-9 23t-22 10-23-7-11-22l-1-126q0-13 10-23t23-10z</StreamGeometry>
2122
<StreamGeometry x:Key="Icons.Copy">M896 811l-128 0c-23 0-43-19-43-43 0-23 19-43 43-43l107 0c13 0 21-9 21-21L896 107c0-13-9-21-21-21L448 85c-13 0-21 9-21 21l0 21c0 23-19 43-43 43-23 0-43-19-43-43L341 85c0-47 38-85 85-85l469 0c47 0 85 38 85 85l0 640C981 772 943 811 896 811zM683 299l0 640c0 47-38 85-85 85L128 1024c-47 0-85-38-85-85L43 299c0-47 38-85 85-85l469 0C644 213 683 252 683 299zM576 299 149 299c-13 0-21 9-21 21l0 597c0 13 9 21 21 21l427 0c13 0 21-9 21-21L597 320C597 307 589 299 576 299z</StreamGeometry>

src/Resources/Locales/en_US.axaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@
158158
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">Workspaces</x:String>
159159
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">Color</x:String>
160160
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">Restore tabs on startup</x:String>
161+
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">Conventional Commit Helper</x:String>
162+
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">Breaking Change:</x:String>
163+
<x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">Closed Issue:</x:String>
164+
<x:String x:Key="Text.ConventionalCommit.Detail" xml:space="preserve">Detail Changes:</x:String>
165+
<x:String x:Key="Text.ConventionalCommit.Scope" xml:space="preserve">Scope:</x:String>
166+
<x:String x:Key="Text.ConventionalCommit.ShortDescription" xml:space="preserve">Short Description:</x:String>
167+
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Type of Change:</x:String>
161168
<x:String x:Key="Text.Copy" xml:space="preserve">Copy</x:String>
162169
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Copy All Text</x:String>
163170
<x:String x:Key="Text.CopyMessage" xml:space="preserve">COPY MESSAGE</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@
161161
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">工作区</x:String>
162162
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">颜色</x:String>
163163
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">启动时恢复打开的仓库</x:String>
164+
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">规范化提交信息生成工具</x:String>
165+
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">破壞性變更說明:</x:String>
166+
<x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">關閉的ISSUE:</x:String>
167+
<x:String x:Key="Text.ConventionalCommit.Detail" xml:space="preserve">詳細說明:</x:String>
168+
<x:String x:Key="Text.ConventionalCommit.Scope" xml:space="preserve">變更模組:</x:String>
169+
<x:String x:Key="Text.ConventionalCommit.ShortDescription" xml:space="preserve">變更簡述:</x:String>
170+
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">變更類型:</x:String>
164171
<x:String x:Key="Text.Copy" xml:space="preserve">复制</x:String>
165172
<x:String x:Key="Text.CopyAllText" xml:space="preserve">复制全部文本</x:String>
166173
<x:String x:Key="Text.CopyMessage" xml:space="preserve">复制内容</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@
161161
<x:String x:Key="Text.ConfigureWorkspace" xml:space="preserve">工作區</x:String>
162162
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">顏色</x:String>
163163
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">啟動時還原上次開啟的存放庫</x:String>
164+
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">規範化提交資訊生成工具</x:String>
165+
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">破坏性更新:</x:String>
166+
<x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">关闭的ISSUE:</x:String>
167+
<x:String x:Key="Text.ConventionalCommit.Detail" xml:space="preserve">详细说明:</x:String>
168+
<x:String x:Key="Text.ConventionalCommit.Scope" xml:space="preserve">变更模块:</x:String>
169+
<x:String x:Key="Text.ConventionalCommit.ShortDescription" xml:space="preserve">变更简述:</x:String>
170+
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">变更类型:</x:String>
164171
<x:String x:Key="Text.Copy" xml:space="preserve">複製</x:String>
165172
<x:String x:Key="Text.CopyAllText" xml:space="preserve">複製全部內容</x:String>
166173
<x:String x:Key="Text.CopyMessage" xml:space="preserve">複製內容</x:String>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using System.ComponentModel.DataAnnotations;
2+
using System.Diagnostics.CodeAnalysis;
3+
using System.Text;
4+
5+
using CommunityToolkit.Mvvm.ComponentModel;
6+
7+
namespace SourceGit.ViewModels
8+
{
9+
public class ConventionalCommitMessageBuilder : ObservableValidator
10+
{
11+
[Required(ErrorMessage = "Type of changes can not be null")]
12+
public Models.ConventionalCommitType Type
13+
{
14+
get => _type;
15+
set => SetProperty(ref _type, value, true);
16+
}
17+
18+
public string Scope
19+
{
20+
get => _scope;
21+
set => SetProperty(ref _scope, value);
22+
}
23+
24+
[Required(ErrorMessage = "Short description can not be empty")]
25+
public string Description
26+
{
27+
get => _description;
28+
set => SetProperty(ref _description, value, true);
29+
}
30+
31+
public string Detail
32+
{
33+
get => _detail;
34+
set => SetProperty(ref _detail, value);
35+
}
36+
37+
public string BreakingChanges
38+
{
39+
get => _breakingChanges;
40+
set => SetProperty(ref _breakingChanges, value);
41+
}
42+
43+
public string ClosedIssue
44+
{
45+
get => _closedIssue;
46+
set => SetProperty(ref _closedIssue, value);
47+
}
48+
49+
public ConventionalCommitMessageBuilder(WorkingCopy wc)
50+
{
51+
_wc = wc;
52+
}
53+
54+
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode")]
55+
public bool Apply()
56+
{
57+
if (HasErrors)
58+
return false;
59+
60+
ValidateAllProperties();
61+
if (HasErrors)
62+
return false;
63+
64+
var builder = new StringBuilder();
65+
builder.Append(_type.Type);
66+
67+
if (!string.IsNullOrEmpty(_scope))
68+
{
69+
builder.Append("(");
70+
builder.Append(_scope);
71+
builder.Append("): ");
72+
}
73+
else
74+
{
75+
builder.Append(": ");
76+
}
77+
78+
builder.Append(_description);
79+
builder.Append("\n\n");
80+
81+
if (!string.IsNullOrEmpty(_detail))
82+
{
83+
builder.Append(_detail);
84+
builder.Append("\n\n");
85+
}
86+
87+
if (!string.IsNullOrEmpty(_breakingChanges))
88+
{
89+
builder.Append("BREAKING CHANGE: ");
90+
builder.Append(_breakingChanges);
91+
builder.Append("\n\n");
92+
}
93+
94+
if (!string.IsNullOrEmpty(_closedIssue))
95+
{
96+
builder.Append("Closed ");
97+
builder.Append(_closedIssue);
98+
}
99+
100+
_wc.CommitMessage = builder.ToString();
101+
return true;
102+
}
103+
104+
private WorkingCopy _wc = null;
105+
private Models.ConventionalCommitType _type = Models.ConventionalCommitType.Supported[0];
106+
private string _scope = string.Empty;
107+
private string _description = string.Empty;
108+
private string _detail = string.Empty;
109+
private string _breakingChanges = string.Empty;
110+
private string _closedIssue = string.Empty;
111+
}
112+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:m="using:SourceGit.Models"
6+
xmlns:vm="using:SourceGit.ViewModels"
7+
xmlns:v="using:SourceGit.Views"
8+
xmlns:c="using:SourceGit.Converters"
9+
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
10+
x:Class="SourceGit.Views.ConventionalCommitMessageBuilder"
11+
x:DataType="vm:ConventionalCommitMessageBuilder"
12+
x:Name="ThisControl"
13+
Icon="/App.ico"
14+
Title="{DynamicResource Text.ConventionalCommit}"
15+
Width="600"
16+
SizeToContent="Height"
17+
CanResize="False"
18+
WindowStartupLocation="CenterOwner">
19+
<Grid RowDefinitions="Auto,Auto,Auto" MinWidth="494">
20+
<!-- TitleBar -->
21+
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
22+
<Border Grid.Column="0" Grid.ColumnSpan="3"
23+
Background="{DynamicResource Brush.TitleBar}"
24+
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
25+
PointerPressed="BeginMoveWindow"/>
26+
27+
<Path Grid.Column="0"
28+
Width="14" Height="14"
29+
Data="{StaticResource Icons.Code}"
30+
Margin="10,0,0,0"
31+
IsVisible="{OnPlatform True, macOS=False}"/>
32+
33+
<v:CaptionButtonsMacOS Grid.Column="0"
34+
Margin="0,2,0,0"
35+
IsCloseButtonOnly="True"
36+
IsVisible="{OnPlatform False, macOS=True}"/>
37+
38+
<TextBlock Grid.Column="0" Grid.ColumnSpan="3"
39+
Classes="bold"
40+
Text="{DynamicResource Text.ConventionalCommit}"
41+
HorizontalAlignment="Center" VerticalAlignment="Center"
42+
IsHitTestVisible="False"/>
43+
44+
<v:CaptionButtons Grid.Column="2"
45+
IsCloseButtonOnly="True"
46+
IsVisible="{OnPlatform True, macOS=False}"/>
47+
</Grid>
48+
49+
<!-- Body -->
50+
<Grid Grid.Row="1" Margin="16,8" RowDefinitions="32,32,32,100,100,32" ColumnDefinitions="Auto,*">
51+
<TextBlock Grid.Row="0" Grid.Column="0"
52+
HorizontalAlignment="Right" VerticalAlignment="Top"
53+
Margin="0,6,8,0"
54+
Text="{DynamicResource Text.ConventionalCommit.Type}"/>
55+
<ComboBox Grid.Row="0" Grid.Column="1"
56+
Height="28" Padding="8,0"
57+
VerticalAlignment="Center" HorizontalAlignment="Stretch"
58+
ItemsSource="{Binding Source={x:Static m:ConventionalCommitType.Supported}}"
59+
SelectedItem="{Binding Type, Mode=TwoWay}">
60+
<ComboBox.ItemTemplate>
61+
<DataTemplate x:DataType="{x:Type m:ConventionalCommitType}">
62+
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Center">
63+
<TextBlock Text="{Binding Type}"/>
64+
<TextBlock Margin="6,0,0,0" Text="{Binding Description}" Foreground="{DynamicResource Brush.FG2}"/>
65+
</StackPanel>
66+
</DataTemplate>
67+
</ComboBox.ItemTemplate>
68+
</ComboBox>
69+
70+
<TextBlock Grid.Row="1" Grid.Column="0"
71+
HorizontalAlignment="Right" VerticalAlignment="Top"
72+
Margin="0,6,8,0"
73+
Text="{DynamicResource Text.ConventionalCommit.Scope}"/>
74+
<TextBox Grid.Row="1" Grid.Column="1"
75+
Height="26"
76+
VerticalAlignment="Center"
77+
CornerRadius="2"
78+
Watermark="{DynamicResource Text.Optional}"
79+
Text="{Binding Scope, Mode=TwoWay}"/>
80+
81+
<TextBlock Grid.Row="2" Grid.Column="0"
82+
HorizontalAlignment="Right" VerticalAlignment="Top"
83+
Margin="0,6,8,0"
84+
Text="{DynamicResource Text.ConventionalCommit.ShortDescription}"/>
85+
<TextBox Grid.Row="2" Grid.Column="1"
86+
Height="26"
87+
VerticalAlignment="Center"
88+
CornerRadius="2"
89+
Text="{Binding Description, Mode=TwoWay}"/>
90+
91+
<TextBlock Grid.Row="3" Grid.Column="0"
92+
HorizontalAlignment="Right" VerticalAlignment="Top"
93+
Margin="0,6,8,0"
94+
Text="{DynamicResource Text.ConventionalCommit.Detail}"/>
95+
<TextBox Grid.Row="3" Grid.Column="1"
96+
Height="96"
97+
AcceptsReturn="True"
98+
AcceptsTab="True"
99+
TextWrapping="Wrap"
100+
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
101+
ScrollViewer.VerticalScrollBarVisibility="Auto"
102+
VerticalAlignment="Center"
103+
VerticalContentAlignment="Top"
104+
CornerRadius="2"
105+
Watermark="{DynamicResource Text.Optional}"
106+
Text="{Binding Detail, Mode=TwoWay}"/>
107+
108+
<TextBlock Grid.Row="4" Grid.Column="0"
109+
HorizontalAlignment="Right" VerticalAlignment="Top"
110+
Margin="0,6,8,0"
111+
Text="{DynamicResource Text.ConventionalCommit.BreakingChanges}"/>
112+
<TextBox Grid.Row="4" Grid.Column="1"
113+
Height="96"
114+
AcceptsReturn="True"
115+
AcceptsTab="True"
116+
TextWrapping="Wrap"
117+
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
118+
ScrollViewer.VerticalScrollBarVisibility="Auto"
119+
VerticalAlignment="Center"
120+
VerticalContentAlignment="Top"
121+
CornerRadius="2"
122+
Watermark="{DynamicResource Text.Optional}"
123+
Text="{Binding BreakingChanges, Mode=TwoWay}"/>
124+
125+
<TextBlock Grid.Row="5" Grid.Column="0"
126+
HorizontalAlignment="Right" VerticalAlignment="Top"
127+
Margin="0,6,8,0"
128+
Text="{DynamicResource Text.ConventionalCommit.ClosedIssue}"/>
129+
<TextBox Grid.Row="5" Grid.Column="1"
130+
Height="26"
131+
VerticalAlignment="Center"
132+
CornerRadius="2"
133+
Watermark="{DynamicResource Text.Optional}"
134+
Text="{Binding ClosedIssue, Mode=TwoWay}"/>
135+
</Grid>
136+
137+
<!-- Apply Button -->
138+
<Button Grid.Row="2"
139+
Classes="flat primary"
140+
Height="32" Width="80"
141+
Margin="0,8,0,16"
142+
HorizontalAlignment="Center"
143+
Content="{DynamicResource Text.Sure}"
144+
Click="OnApplyClicked"/>
145+
</Grid>
146+
</v:ChromelessWindow>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Avalonia.Input;
2+
using Avalonia.Interactivity;
3+
4+
namespace SourceGit.Views
5+
{
6+
public partial class ConventionalCommitMessageBuilder : ChromelessWindow
7+
{
8+
public ConventionalCommitMessageBuilder()
9+
{
10+
InitializeComponent();
11+
}
12+
13+
private void BeginMoveWindow(object _, PointerPressedEventArgs e)
14+
{
15+
BeginMoveDrag(e);
16+
}
17+
18+
private void OnApplyClicked(object _, RoutedEventArgs e)
19+
{
20+
if (DataContext is ViewModels.ConventionalCommitMessageBuilder builder)
21+
{
22+
if (builder.Apply())
23+
Close();
24+
}
25+
26+
e.Handled = true;
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)