Forge
csharpdeeb25a2
1#nullable enable
2using CascadeIDE.Features.Launch.Application;
3using System.Collections.ObjectModel;
4using CommunityToolkit.Mvvm.ComponentModel;
5using CommunityToolkit.Mvvm.Input;
6
7namespace CascadeIDE.ViewModels;
8
9/// <summary>Селектор launch profile, импорт <c>launchSettings.json</c> (ADR 0090).</summary>
10public partial class MainWindowViewModel
11{
12 public ObservableCollection<string> LaunchProfileIds { get; } = new();
13
14 [ObservableProperty]
15 private string? _selectedLaunchProfileId;
16
17 private bool _suspendLaunchProfileSelectionPersistence;
18
19 /// <summary>Есть ≥1 именованного профиля в <c>launch-profiles.toml</c>.</summary>
20 public bool ShowLaunchProfilePicker => LaunchProfileIds.Count > 0;
21
22 partial void OnSelectedLaunchProfileIdChanged(string? value)
23 {
24 if (_suspendLaunchProfileSelectionPersistence)
25 return;
26 var sln = Workspace.SolutionPath;
27 if (string.IsNullOrEmpty(sln) || string.IsNullOrEmpty(value))
28 return;
29 _ = LaunchProfilesStore.TrySetActiveProfile(sln, value, out _);
30 OnPropertyChanged(nameof(StartupProjectBanner));
31 }
32
33 public void RefreshLaunchProfilePickerFromStore()
34 {
35 _suspendLaunchProfileSelectionPersistence = true;
36 try
37 {
38 LaunchProfileIds.Clear();
39 var sln = Workspace.SolutionPath;
40 if (string.IsNullOrEmpty(sln))
41 {
42 SelectedLaunchProfileId = null;
43 return;
44 }
45
46 if (!LaunchProfilesStore.TryGetOrderedProfileIds(sln, out var names, out _))
47 {
48 SelectedLaunchProfileId = null;
49 return;
50 }
51
52 foreach (var n in names)
53 LaunchProfileIds.Add(n);
54
55 if (LaunchProfilesStore.TryGetActiveProfileName(sln, out var active, out _) && !string.IsNullOrEmpty(active))
56 {
57 var match = LaunchProfileIds.FirstOrDefault(x => string.Equals(x, active, StringComparison.OrdinalIgnoreCase));
58 SelectedLaunchProfileId = match ?? LaunchProfileIds[0];
59 }
60 else
61 SelectedLaunchProfileId = LaunchProfileIds[0];
62 }
63 finally
64 {
65 _suspendLaunchProfileSelectionPersistence = false;
66 }
67
68 OnPropertyChanged(nameof(ShowLaunchProfilePicker));
69 OnPropertyChanged(nameof(StartupProjectBanner));
70 }
71
72 [RelayCommand(CanExecute = nameof(CanImportLaunchSettingsFromSelection))]
73 private async Task ImportLaunchSettingsFromSelectionAsync()
74 {
75 var item = Workspace.SelectedSolutionItem;
76 var path = item?.FullPath;
77 if (string.IsNullOrEmpty(path) || !path.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase))
78 return;
79
80 var sln = Workspace.SolutionPath;
81 if (string.IsNullOrEmpty(sln))
82 return;
83
84 var solutionDir = Services.BreakpointsFileService.GetWorkspaceRoot(sln);
85 if (string.IsNullOrEmpty(solutionDir))
86 return;
87
88 if (!LaunchProjectRelativePath.TryGetRelativeToSolutionDirectory(solutionDir, path, out var rel, out var pathErr))
89 {
90 await ShowDebugInfoAsync("launchSettings.json", pathErr).ConfigureAwait(false);
91 return;
92 }
93
94 if (!LaunchProfilesStore.TryImportFromLaunchSettings(sln, rel, out var n, out var err) || !string.IsNullOrEmpty(err))
95 {
96 await ShowDebugInfoAsync("Импорт launch profiles", err ?? "import_failed").ConfigureAwait(false);
97 return;
98 }
99
100 RefreshLaunchProfilePickerFromStore();
101 await ShowDebugInfoAsync("Импорт launch profiles", $"Скопировано профилей (Kestrel/Project) в {LaunchProfilesStore.FileName}: {n}.").ConfigureAwait(false);
102 }
103
104 private bool CanImportLaunchSettingsFromSelection() =>
105 !string.IsNullOrEmpty(Workspace.SolutionPath) &&
106 !string.IsNullOrEmpty(Workspace.SelectedSolutionItem?.FullPath) &&
107 Workspace.SelectedSolutionItem!.FullPath.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase);
108}
109
View only · write via MCP/CIDE