Skip to content

Commit 750ca8e

Browse files
committed
refactor: use custom view locator to create new window/dialog (#1216)
Signed-off-by: leo <[email protected]> (cherry picked from commit 3e6f2b2)
1 parent 8611370 commit 750ca8e

15 files changed

+158
-164
lines changed

src/App.Commands.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ public static bool IsCheckForUpdateCommandVisible
3737
}
3838
}
3939

40-
public static readonly Command OpenPreferencesCommand = new Command(_ => OpenDialog(new Views.Preferences()));
41-
public static readonly Command OpenHotkeysCommand = new Command(_ => OpenDialog(new Views.Hotkeys()));
40+
public static readonly Command OpenPreferencesCommand = new Command(_ => ShowWindow(new Views.Preferences(), false));
41+
public static readonly Command OpenHotkeysCommand = new Command(_ => ShowWindow(new Views.Hotkeys(), false));
4242
public static readonly Command OpenAppDataDirCommand = new Command(_ => Native.OS.OpenInFileManager(Native.OS.DataDir));
43-
public static readonly Command OpenAboutCommand = new Command(_ => OpenDialog(new Views.About()));
43+
public static readonly Command OpenAboutCommand = new Command(_ => ShowWindow(new Views.About(), false));
4444
public static readonly Command CheckForUpdateCommand = new Command(_ => (Current as App)?.Check4Update(true));
4545
public static readonly Command QuitCommand = new Command(_ => Quit(0));
4646
public static readonly Command CopyTextBlockCommand = new Command(p =>

src/App.axaml.cs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,36 @@ private static void LogException(Exception ex)
105105
#endregion
106106

107107
#region Utility Functions
108-
public static void OpenDialog(Window window)
108+
public static void ShowWindow(object data, bool showAsDialog)
109109
{
110-
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
111-
window.ShowDialog(owner);
110+
if (data is Views.ChromelessWindow window)
111+
{
112+
if (showAsDialog && Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
113+
window.ShowDialog(owner);
114+
else
115+
window.Show();
116+
117+
return;
118+
}
119+
120+
var dataTypeName = data.GetType().FullName;
121+
if (string.IsNullOrEmpty(dataTypeName) || !dataTypeName.Contains(".ViewModels.", StringComparison.Ordinal))
122+
return;
123+
124+
var viewTypeName = dataTypeName.Replace(".ViewModels.", ".Views.");
125+
var viewType = Type.GetType(viewTypeName);
126+
if (viewType == null || !viewType.IsSubclassOf(typeof(Views.ChromelessWindow)))
127+
return;
128+
129+
window = Activator.CreateInstance(viewType) as Views.ChromelessWindow;
130+
if (window != null)
131+
{
132+
window.DataContext = data;
133+
if (showAsDialog && Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
134+
window.ShowDialog(owner);
135+
else
136+
window.Show();
137+
}
112138
}
113139

114140
public static void RaiseException(string context, string message)
@@ -598,11 +624,7 @@ private void ShowSelfUpdateResult(object data)
598624
{
599625
Dispatcher.UIThread.Post(() =>
600626
{
601-
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime { MainWindow: { } owner })
602-
{
603-
var dialog = new Views.SelfUpdate() { DataContext = new ViewModels.SelfUpdate() { Data = data } };
604-
dialog.ShowDialog(owner);
605-
}
627+
ShowWindow(new ViewModels.SelfUpdate() { Data = data }, true);
606628
});
607629
}
608630

src/ViewModels/AIAssistant.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
6+
using Avalonia.Threading;
7+
8+
using CommunityToolkit.Mvvm.ComponentModel;
9+
10+
namespace SourceGit.ViewModels
11+
{
12+
public class AIAssistant : ObservableObject
13+
{
14+
public bool IsGenerating
15+
{
16+
get => _isGenerating;
17+
private set => SetProperty(ref _isGenerating, value);
18+
}
19+
20+
public string Text
21+
{
22+
get => _text;
23+
private set => SetProperty(ref _text, value);
24+
}
25+
26+
public AIAssistant(Repository repo, Models.OpenAIService service, List<Models.Change> changes, Action<string> onApply)
27+
{
28+
_repo = repo;
29+
_service = service;
30+
_changes = changes;
31+
_onApply = onApply;
32+
_cancel = new CancellationTokenSource();
33+
34+
Gen();
35+
}
36+
37+
public void Regen()
38+
{
39+
if (_cancel is { IsCancellationRequested: false })
40+
_cancel.Cancel();
41+
42+
Gen();
43+
}
44+
45+
public void Apply()
46+
{
47+
_onApply?.Invoke(Text);
48+
}
49+
50+
public void Cancel()
51+
{
52+
_cancel?.Cancel();
53+
}
54+
55+
private void Gen()
56+
{
57+
Text = string.Empty;
58+
IsGenerating = true;
59+
60+
_cancel = new CancellationTokenSource();
61+
Task.Run(() =>
62+
{
63+
new Commands.GenerateCommitMessage(_service, _repo.FullPath, _changes, _cancel.Token, message =>
64+
{
65+
Dispatcher.UIThread.Invoke(() => Text = message);
66+
}).Exec();
67+
68+
Dispatcher.UIThread.Invoke(() => IsGenerating = false);
69+
}, _cancel.Token);
70+
}
71+
72+
private readonly Repository _repo = null;
73+
private Models.OpenAIService _service = null;
74+
private List<Models.Change> _changes = null;
75+
private Action<string> _onApply = null;
76+
private CancellationTokenSource _cancel = null;
77+
private bool _isGenerating = false;
78+
private string _text = string.Empty;
79+
}
80+
}

src/ViewModels/CommitDetail.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,7 @@ public ContextMenu CreateChangeContextMenu(Models.Change change)
332332
history.Icon = App.CreateMenuIcon("Icons.Histories");
333333
history.Click += (_, ev) =>
334334
{
335-
var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, change.Path, _commit.SHA) };
336-
window.Show();
335+
App.ShowWindow(new FileHistories(_repo, change.Path, _commit.SHA), false);
337336
ev.Handled = true;
338337
};
339338

@@ -343,8 +342,7 @@ public ContextMenu CreateChangeContextMenu(Models.Change change)
343342
blame.IsEnabled = change.Index != Models.ChangeState.Deleted;
344343
blame.Click += (_, ev) =>
345344
{
346-
var window = new Views.Blame() { DataContext = new Blame(_repo.FullPath, change.Path, _commit.SHA) };
347-
window.Show();
345+
App.ShowWindow(new Blame(_repo.FullPath, change.Path, _commit.SHA), false);
348346
ev.Handled = true;
349347
};
350348

@@ -508,8 +506,7 @@ public ContextMenu CreateRevisionFileContextMenu(Models.Object file)
508506
history.Icon = App.CreateMenuIcon("Icons.Histories");
509507
history.Click += (_, ev) =>
510508
{
511-
var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, file.Path, _commit.SHA) };
512-
window.Show();
509+
App.ShowWindow(new FileHistories(_repo, file.Path, _commit.SHA), false);
513510
ev.Handled = true;
514511
};
515512

@@ -519,8 +516,7 @@ public ContextMenu CreateRevisionFileContextMenu(Models.Object file)
519516
blame.IsEnabled = file.Type == Models.ObjectType.Blob;
520517
blame.Click += (_, ev) =>
521518
{
522-
var window = new Views.Blame() { DataContext = new Blame(_repo.FullPath, file.Path, _commit.SHA) };
523-
window.Show();
519+
App.ShowWindow(new Blame(_repo.FullPath, file.Path, _commit.SHA), false);
524520
ev.Handled = true;
525521
};
526522

src/ViewModels/Histories.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -570,11 +570,7 @@ public ContextMenu MakeContextMenu(ListBox list)
570570
return;
571571
}
572572

573-
App.OpenDialog(new Views.InteractiveRebase()
574-
{
575-
DataContext = new InteractiveRebase(_repo, current, commit)
576-
});
577-
573+
App.ShowWindow(new InteractiveRebase(_repo, current, commit), true);
578574
e.Handled = true;
579575
};
580576

src/ViewModels/Launcher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ public ContextMenu CreateContextForWorkspace()
380380
configure.Header = App.Text("Workspace.Configure");
381381
configure.Click += (_, e) =>
382382
{
383-
App.OpenDialog(new Views.ConfigureWorkspace() { DataContext = new ConfigureWorkspace() });
383+
App.ShowWindow(new ConfigureWorkspace(), true);
384384
e.Handled = true;
385385
};
386386
menu.Items.Add(configure);

src/ViewModels/Repository.cs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,8 +1405,7 @@ public ContextMenu CreateContextMenuForGitLFS()
14051405
{
14061406
locks.Click += (_, e) =>
14071407
{
1408-
var dialog = new Views.LFSLocks() { DataContext = new LFSLocks(this, _remotes[0].Name) };
1409-
App.OpenDialog(dialog);
1408+
App.ShowWindow(new LFSLocks(this, _remotes[0].Name), true);
14101409
e.Handled = true;
14111410
};
14121411
}
@@ -1419,8 +1418,7 @@ public ContextMenu CreateContextMenuForGitLFS()
14191418
lockRemote.Header = remoteName;
14201419
lockRemote.Click += (_, e) =>
14211420
{
1422-
var dialog = new Views.LFSLocks() { DataContext = new LFSLocks(this, remoteName) };
1423-
App.OpenDialog(dialog);
1421+
App.ShowWindow(new LFSLocks(this, remoteName), true);
14241422
e.Handled = true;
14251423
};
14261424
locks.Items.Add(lockRemote);
@@ -1706,10 +1704,7 @@ public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
17061704
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
17071705
compareWithHead.Click += (_, _) =>
17081706
{
1709-
App.OpenDialog(new Views.BranchCompare()
1710-
{
1711-
DataContext = new BranchCompare(_fullpath, branch, _currentBranch)
1712-
});
1707+
App.ShowWindow(new BranchCompare(_fullpath, branch, _currentBranch), false);
17131708
};
17141709
menu.Items.Add(new MenuItem() { Header = "-" });
17151710
menu.Items.Add(compareWithHead);
@@ -1989,10 +1984,7 @@ public ContextMenu CreateContextMenuForRemoteBranch(Models.Branch branch)
19891984
compareWithHead.Icon = App.CreateMenuIcon("Icons.Compare");
19901985
compareWithHead.Click += (_, _) =>
19911986
{
1992-
App.OpenDialog(new Views.BranchCompare()
1993-
{
1994-
DataContext = new BranchCompare(_fullpath, branch, _currentBranch)
1995-
});
1987+
App.ShowWindow(new BranchCompare(_fullpath, branch, _currentBranch), false);
19961988
};
19971989
menu.Items.Add(compareWithHead);
19981990

src/ViewModels/WorkingCopy.cs

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,7 @@ public void OpenExternalMergeToolAllConflicts()
323323

324324
public void OpenAssumeUnchanged()
325325
{
326-
App.OpenDialog(new Views.AssumeUnchangedManager()
327-
{
328-
DataContext = new AssumeUnchangedManager(_repo)
329-
});
326+
App.ShowWindow(new AssumeUnchangedManager(_repo), true);
330327
}
331328

332329
public void StashAll(bool autoStart)
@@ -726,8 +723,7 @@ public ContextMenu CreateContextMenuForUnstagedChanges()
726723
history.Icon = App.CreateMenuIcon("Icons.Histories");
727724
history.Click += (_, e) =>
728725
{
729-
var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, change.Path) };
730-
window.Show();
726+
App.ShowWindow(new FileHistories(_repo, change.Path), false);
731727
e.Handled = true;
732728
};
733729

@@ -1093,8 +1089,7 @@ public ContextMenu CreateContextMenuForStagedChanges()
10931089
{
10941090
ai.Click += (_, e) =>
10951091
{
1096-
var dialog = new Views.AIAssistant(services[0], _repo.FullPath, this, _selectedStaged);
1097-
App.OpenDialog(dialog);
1092+
App.ShowWindow(new AIAssistant(_repo, services[0], _selectedStaged, t => CommitMessage = t), true);
10981093
e.Handled = true;
10991094
};
11001095
}
@@ -1108,8 +1103,7 @@ public ContextMenu CreateContextMenuForStagedChanges()
11081103
item.Header = service.Name;
11091104
item.Click += (_, e) =>
11101105
{
1111-
var dialog = new Views.AIAssistant(dup, _repo.FullPath, this, _selectedStaged);
1112-
App.OpenDialog(dialog);
1106+
App.ShowWindow(new AIAssistant(_repo, dup, _selectedStaged, t => CommitMessage = t), true);
11131107
e.Handled = true;
11141108
};
11151109

@@ -1193,8 +1187,7 @@ public ContextMenu CreateContextMenuForStagedChanges()
11931187
history.Icon = App.CreateMenuIcon("Icons.Histories");
11941188
history.Click += (_, e) =>
11951189
{
1196-
var window = new Views.FileHistories() { DataContext = new FileHistories(_repo, change.Path) };
1197-
window.Show();
1190+
App.ShowWindow(new FileHistories(_repo, change.Path), false);
11981191
e.Handled = true;
11991192
};
12001193

@@ -1490,8 +1483,7 @@ public ContextMenu CreateContextForOpenAI()
14901483

14911484
if (services.Count == 1)
14921485
{
1493-
var dialog = new Views.AIAssistant(services[0], _repo.FullPath, this, _staged);
1494-
App.OpenDialog(dialog);
1486+
App.ShowWindow(new AIAssistant(_repo, services[0], _staged, t => CommitMessage = t), true);
14951487
return null;
14961488
}
14971489

@@ -1503,8 +1495,7 @@ public ContextMenu CreateContextForOpenAI()
15031495
item.Header = service.Name;
15041496
item.Click += (_, e) =>
15051497
{
1506-
var dialog = new Views.AIAssistant(dup, _repo.FullPath, this, _staged);
1507-
App.OpenDialog(dialog);
1498+
App.ShowWindow(new AIAssistant(_repo, dup, _staged, t => CommitMessage = t), true);
15081499
e.Handled = true;
15091500
};
15101501

@@ -1705,29 +1696,15 @@ private void DoCommit(bool autoStage, bool autoPush, bool allowEmpty = false, bo
17051696
if (!string.IsNullOrEmpty(_filter) && _staged.Count > _visibleStaged.Count && !confirmWithFilter)
17061697
{
17071698
var confirmMessage = App.Text("WorkingCopy.ConfirmCommitWithFilter", _staged.Count, _visibleStaged.Count, _staged.Count - _visibleStaged.Count);
1708-
App.OpenDialog(new Views.ConfirmCommit()
1709-
{
1710-
DataContext = new ConfirmCommit(confirmMessage, () =>
1711-
{
1712-
DoCommit(autoStage, autoPush, allowEmpty, true);
1713-
})
1714-
});
1715-
1699+
App.ShowWindow(new ConfirmCommit(confirmMessage, () => DoCommit(autoStage, autoPush, allowEmpty, true)), true);
17161700
return;
17171701
}
17181702

17191703
if (!_useAmend && !allowEmpty)
17201704
{
17211705
if ((autoStage && _count == 0) || (!autoStage && _staged.Count == 0))
17221706
{
1723-
App.OpenDialog(new Views.ConfirmEmptyCommit()
1724-
{
1725-
DataContext = new ConfirmEmptyCommit(_count > 0, stageAll =>
1726-
{
1727-
DoCommit(stageAll, autoPush, true, confirmWithFilter);
1728-
})
1729-
});
1730-
1707+
App.ShowWindow(new ConfirmEmptyCommit(_count > 0, stageAll => DoCommit(stageAll, autoPush, true, confirmWithFilter)), true);
17311708
return;
17321709
}
17331710
}

src/Views/AIAssistant.axaml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
xmlns:c="using:SourceGit.Converters"
88
mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="120"
99
x:Class="SourceGit.Views.AIAssistant"
10+
x:DataType="vm:AIAssistant"
1011
x:Name="ThisControl"
1112
Icon="/App.ico"
1213
Title="{DynamicResource Text.AIAssistant}"
@@ -48,20 +49,22 @@
4849
<!-- Options -->
4950
<Border Grid.Row="2" Margin="0,0,0,8">
5051
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
51-
<v:LoadingIcon x:Name="IconInProgress" Width="14" Height="14" Margin="0,0,8,0"/>
52+
<v:LoadingIcon Width="14" Height="14"
53+
Margin="0,0,8,0"
54+
IsVisible="{Binding IsGenerating}"/>
5255
<Button Classes="flat"
53-
x:Name="BtnGenerateCommitMessage"
5456
Height="28"
5557
Margin="0,0,8,0"
5658
Padding="12,0"
5759
Content="{DynamicResource Text.AIAssistant.Use}"
58-
Click="OnGenerateCommitMessage"/>
60+
IsEnabled="{Binding !IsGenerating}"
61+
Click="OnApply"/>
5962
<Button Classes="flat"
60-
x:Name="BtnRegenerate"
6163
Height="28"
6264
Padding="12,0"
6365
Content="{DynamicResource Text.AIAssistant.Regen}"
64-
Click="OnRegen"/>
66+
IsEnabled="{Binding !IsGenerating}"
67+
Command="{Binding Regen}"/>
6568
</StackPanel>
6669
</Border>
6770
</Grid>

0 commit comments

Comments
 (0)