Skip to content

Commit c08f158

Browse files
committed
refactor: move context menu creation from ViewModels to Views (PART 9)
Signed-off-by: leo <longshuang@msn.cn>
1 parent fa44d9c commit c08f158

File tree

3 files changed

+149
-149
lines changed

3 files changed

+149
-149
lines changed

src/Resources/Styles.axaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -844,10 +844,6 @@
844844
<v:NameHighlightedTextBlock Text="{Binding}" VerticalAlignment="Center"/>
845845
</DataTemplate>
846846

847-
<DataTemplate DataType="vm:CommitMessageRecord">
848-
<TextBlock Text="{Binding Subject}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis"/>
849-
</DataTemplate>
850-
851847
<DataTemplate DataType="vm:FilterModeInGraph">
852848
<v:FilterModeInGraph/>
853849
</DataTemplate>

src/ViewModels/WorkingCopy.cs

Lines changed: 10 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111

1212
namespace SourceGit.ViewModels
1313
{
14-
public record CommitMessageRecord(string subject)
15-
{
16-
public string Subject { get; set; } = subject;
17-
}
18-
1914
public class WorkingCopy : ObservableObject, IDisposable
2015
{
16+
public Repository Repository
17+
{
18+
get => _repo;
19+
}
20+
2121
public bool IncludeUntracked
2222
{
2323
get => _repo.IncludeUntracked;
@@ -564,6 +564,11 @@ await Dispatcher.UIThread.InvokeAsync(() =>
564564
}
565565
}
566566

567+
public void ApplyCommitMessageTemplate(Models.CommitTemplate tmpl)
568+
{
569+
CommitMessage = tmpl.Apply(_repo.CurrentBranch, _staged);
570+
}
571+
567572
public void Commit()
568573
{
569574
DoCommit(false, false);
@@ -1602,137 +1607,6 @@ public ContextMenu CreateContextMenuForStagedChanges(string selectedSingleFolder
16021607
return menu;
16031608
}
16041609

1605-
public ContextMenu CreateContextMenuForCommitMessages()
1606-
{
1607-
var menu = new ContextMenu();
1608-
1609-
var gitTemplate = new Commands.Config(_repo.FullPath).GetAsync("commit.template").Result;
1610-
var templateCount = _repo.Settings.CommitTemplates.Count;
1611-
if (templateCount == 0 && string.IsNullOrEmpty(gitTemplate))
1612-
{
1613-
menu.Items.Add(new MenuItem()
1614-
{
1615-
Header = App.Text("WorkingCopy.NoCommitTemplates"),
1616-
Icon = App.CreateMenuIcon("Icons.Code"),
1617-
IsEnabled = false
1618-
});
1619-
}
1620-
else
1621-
{
1622-
for (int i = 0; i < templateCount; i++)
1623-
{
1624-
var template = _repo.Settings.CommitTemplates[i];
1625-
var item = new MenuItem();
1626-
item.Header = App.Text("WorkingCopy.UseCommitTemplate", template.Name);
1627-
item.Icon = App.CreateMenuIcon("Icons.Code");
1628-
item.Click += (_, e) =>
1629-
{
1630-
CommitMessage = template.Apply(_repo.CurrentBranch, _staged);
1631-
e.Handled = true;
1632-
};
1633-
menu.Items.Add(item);
1634-
}
1635-
1636-
if (!string.IsNullOrEmpty(gitTemplate))
1637-
{
1638-
if (!Path.IsPathRooted(gitTemplate))
1639-
gitTemplate = Native.OS.GetAbsPath(_repo.FullPath, gitTemplate);
1640-
1641-
var friendlyName = gitTemplate;
1642-
if (!OperatingSystem.IsWindows())
1643-
{
1644-
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
1645-
var prefixLen = home.EndsWith('/') ? home.Length - 1 : home.Length;
1646-
if (gitTemplate.StartsWith(home, StringComparison.Ordinal))
1647-
friendlyName = $"~{gitTemplate.AsSpan(prefixLen)}";
1648-
}
1649-
1650-
var gitTemplateItem = new MenuItem();
1651-
gitTemplateItem.Header = App.Text("WorkingCopy.UseCommitTemplate", friendlyName);
1652-
gitTemplateItem.Icon = App.CreateMenuIcon("Icons.Code");
1653-
gitTemplateItem.Click += (_, e) =>
1654-
{
1655-
if (File.Exists(gitTemplate))
1656-
CommitMessage = File.ReadAllText(gitTemplate);
1657-
e.Handled = true;
1658-
};
1659-
menu.Items.Add(gitTemplateItem);
1660-
}
1661-
}
1662-
1663-
menu.Items.Add(new MenuItem() { Header = "-" });
1664-
1665-
var historiesCount = _repo.Settings.CommitMessages.Count;
1666-
if (historiesCount == 0)
1667-
{
1668-
menu.Items.Add(new MenuItem()
1669-
{
1670-
Header = App.Text("WorkingCopy.NoCommitHistories"),
1671-
Icon = App.CreateMenuIcon("Icons.Histories"),
1672-
IsEnabled = false
1673-
});
1674-
}
1675-
else
1676-
{
1677-
for (int i = 0; i < historiesCount; i++)
1678-
{
1679-
var dup = _repo.Settings.CommitMessages[i].Trim();
1680-
var message = dup.ReplaceLineEndings(" ");
1681-
var item = new MenuItem();
1682-
item.Header = new CommitMessageRecord(message);
1683-
item.Icon = App.CreateMenuIcon("Icons.Histories");
1684-
item.Click += (_, e) =>
1685-
{
1686-
CommitMessage = dup;
1687-
e.Handled = true;
1688-
};
1689-
1690-
menu.Items.Add(item);
1691-
}
1692-
}
1693-
1694-
return menu;
1695-
}
1696-
1697-
public ContextMenu CreateContextForOpenAI()
1698-
{
1699-
if (_staged == null || _staged.Count == 0)
1700-
{
1701-
App.RaiseException(_repo.FullPath, "No files added to commit!");
1702-
return null;
1703-
}
1704-
1705-
var services = _repo.GetPreferredOpenAIServices();
1706-
if (services.Count == 0)
1707-
{
1708-
App.RaiseException(_repo.FullPath, "Bad configuration for OpenAI");
1709-
return null;
1710-
}
1711-
1712-
if (services.Count == 1)
1713-
{
1714-
_ = App.ShowDialog(new AIAssistant(_repo, services[0], _staged, t => CommitMessage = t));
1715-
return null;
1716-
}
1717-
1718-
var menu = new ContextMenu() { Placement = PlacementMode.TopEdgeAlignedLeft };
1719-
foreach (var service in services)
1720-
{
1721-
var dup = service;
1722-
var item = new MenuItem();
1723-
item.Header = service.Name;
1724-
item.Click += async (_, e) =>
1725-
{
1726-
await App.ShowDialog(new AIAssistant(_repo, dup, _staged, t => CommitMessage = t));
1727-
e.Handled = true;
1728-
};
1729-
1730-
menu.Items.Add(item);
1731-
}
1732-
1733-
return menu;
1734-
}
1735-
17361610
private List<Models.Change> GetVisibleChanges(List<Models.Change> changes)
17371611
{
17381612
if (string.IsNullOrEmpty(_filter))

src/Views/CommitMessageTextBox.axaml.cs

Lines changed: 139 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
using System;
2+
using System.IO;
23

34
using Avalonia;
45
using Avalonia.Controls;
56
using Avalonia.Input;
67
using Avalonia.Interactivity;
8+
using Avalonia.Layout;
9+
using Avalonia.Media;
710

811
namespace SourceGit.Views
912
{
@@ -170,37 +173,164 @@ private void OnDescriptionTextBoxPreviewKeyDown(object _, KeyEventArgs e)
170173
}
171174
}
172175

173-
private void OnOpenCommitMessagePicker(object sender, RoutedEventArgs e)
176+
private async void OnOpenCommitMessagePicker(object sender, RoutedEventArgs e)
174177
{
175-
if (sender is Button button && DataContext is ViewModels.WorkingCopy vm)
178+
if (sender is Button button && DataContext is ViewModels.WorkingCopy vm && ShowAdvancedOptions)
176179
{
177-
var menu = vm.CreateContextMenuForCommitMessages();
180+
var repo = vm.Repository;
181+
var menu = new ContextMenu();
182+
183+
var gitTemplate = await new Commands.Config(repo.FullPath).GetAsync("commit.template");
184+
var templateCount = repo.Settings.CommitTemplates.Count;
185+
if (templateCount == 0 && string.IsNullOrEmpty(gitTemplate))
186+
{
187+
menu.Items.Add(new MenuItem()
188+
{
189+
Header = App.Text("WorkingCopy.NoCommitTemplates"),
190+
Icon = App.CreateMenuIcon("Icons.Code"),
191+
IsEnabled = false
192+
});
193+
}
194+
else
195+
{
196+
for (int i = 0; i < templateCount; i++)
197+
{
198+
var template = repo.Settings.CommitTemplates[i];
199+
var item = new MenuItem();
200+
item.Header = App.Text("WorkingCopy.UseCommitTemplate", template.Name);
201+
item.Icon = App.CreateMenuIcon("Icons.Code");
202+
item.Click += (_, e) =>
203+
{
204+
vm.ApplyCommitMessageTemplate(template);
205+
e.Handled = true;
206+
};
207+
menu.Items.Add(item);
208+
}
209+
210+
if (!string.IsNullOrEmpty(gitTemplate))
211+
{
212+
if (!Path.IsPathRooted(gitTemplate))
213+
gitTemplate = Native.OS.GetAbsPath(repo.FullPath, gitTemplate);
214+
215+
var friendlyName = gitTemplate;
216+
if (!OperatingSystem.IsWindows())
217+
{
218+
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
219+
var prefixLen = home.EndsWith('/') ? home.Length - 1 : home.Length;
220+
if (gitTemplate.StartsWith(home, StringComparison.Ordinal))
221+
friendlyName = $"~{gitTemplate.AsSpan(prefixLen)}";
222+
}
223+
224+
var gitTemplateItem = new MenuItem();
225+
gitTemplateItem.Header = App.Text("WorkingCopy.UseCommitTemplate", friendlyName);
226+
gitTemplateItem.Icon = App.CreateMenuIcon("Icons.Code");
227+
gitTemplateItem.Click += (_, e) =>
228+
{
229+
if (File.Exists(gitTemplate))
230+
vm.CommitMessage = File.ReadAllText(gitTemplate);
231+
e.Handled = true;
232+
};
233+
menu.Items.Add(gitTemplateItem);
234+
}
235+
}
236+
237+
menu.Items.Add(new MenuItem() { Header = "-" });
238+
239+
var historiesCount = repo.Settings.CommitMessages.Count;
240+
if (historiesCount == 0)
241+
{
242+
menu.Items.Add(new MenuItem()
243+
{
244+
Header = App.Text("WorkingCopy.NoCommitHistories"),
245+
Icon = App.CreateMenuIcon("Icons.Histories"),
246+
IsEnabled = false
247+
});
248+
}
249+
else
250+
{
251+
for (int i = 0; i < historiesCount; i++)
252+
{
253+
var dup = repo.Settings.CommitMessages[i].Trim();
254+
var header = new TextBlock()
255+
{
256+
Text = dup.ReplaceLineEndings(" "),
257+
VerticalAlignment = VerticalAlignment.Center,
258+
TextTrimming = TextTrimming.CharacterEllipsis
259+
};
260+
261+
var item = new MenuItem();
262+
item.Header = header;
263+
item.Icon = App.CreateMenuIcon("Icons.Histories");
264+
item.Click += (_, e) =>
265+
{
266+
vm.CommitMessage = dup;
267+
e.Handled = true;
268+
};
269+
270+
menu.Items.Add(item);
271+
}
272+
}
273+
178274
menu.Placement = PlacementMode.TopEdgeAlignedLeft;
179275
menu.Open(button);
180276
}
181277

182278
e.Handled = true;
183279
}
184280

185-
private void OnOpenOpenAIHelper(object sender, RoutedEventArgs e)
281+
private async void OnOpenOpenAIHelper(object sender, RoutedEventArgs e)
186282
{
187-
if (DataContext is ViewModels.WorkingCopy vm && sender is Control control)
283+
if (DataContext is ViewModels.WorkingCopy vm && sender is Control control && ShowAdvancedOptions)
188284
{
189-
var menu = vm.CreateContextForOpenAI();
190-
menu?.Open(control);
285+
var repo = vm.Repository;
286+
287+
if (vm.Staged == null || vm.Staged.Count == 0)
288+
{
289+
App.RaiseException(repo.FullPath, "No files added to commit!");
290+
return;
291+
}
292+
293+
var services = repo.GetPreferredOpenAIServices();
294+
if (services.Count == 0)
295+
{
296+
App.RaiseException(repo.FullPath, "Bad configuration for OpenAI");
297+
return;
298+
}
299+
300+
if (services.Count == 1)
301+
{
302+
await App.ShowDialog(new ViewModels.AIAssistant(repo, services[0], vm.Staged, t => vm.CommitMessage = t));
303+
return;
304+
}
305+
306+
var menu = new ContextMenu() { Placement = PlacementMode.TopEdgeAlignedLeft };
307+
foreach (var service in services)
308+
{
309+
var dup = service;
310+
var item = new MenuItem();
311+
item.Header = service.Name;
312+
item.Click += async (_, e) =>
313+
{
314+
await App.ShowDialog(new ViewModels.AIAssistant(repo, dup, vm.Staged, t => vm.CommitMessage = t));
315+
e.Handled = true;
316+
};
317+
318+
menu.Items.Add(item);
319+
}
320+
menu.Open(control);
191321
}
192322

193323
e.Handled = true;
194324
}
195325

196-
private void OnOpenConventionalCommitHelper(object _, RoutedEventArgs e)
326+
private async void OnOpenConventionalCommitHelper(object _, RoutedEventArgs e)
197327
{
198328
var toplevel = TopLevel.GetTopLevel(this);
199329
if (toplevel is Window owner)
200330
{
201331
var vm = new ViewModels.ConventionalCommitMessageBuilder(text => Text = text);
202332
var builder = new ConventionalCommitMessageBuilder() { DataContext = vm };
203-
builder.ShowDialog(owner);
333+
await builder.ShowDialog(owner);
204334
}
205335

206336
e.Handled = true;

0 commit comments

Comments
 (0)