Forge
csharp4405de34
1using System.Threading;
2using System.Threading.Tasks;
3using CascadeIDE.Features.Workspace;
4using CascadeIDE.Features.Workspace.Application;
5using CascadeIDE.Models;
6using CascadeIDE.Services;
7using CommunityToolkit.Mvvm.Input;
8
9namespace CascadeIDE.ViewModels;
10
11/// <summary>Загрузка решения, Ollama install; сборка — <see cref="Features.Build.MainWindowBuildSessionViewModel"/>.</summary>
12public partial class MainWindowViewModel
13{
14 public void LoadSolution(string path)
15 {
16 _ = LoadSolutionAsync(path);
17 }
18
19 /// <summary>Загрузка решения: парсинг .sln/папки в пуле потоков, применение к UI — на UI-потоке.</summary>
20 public async Task LoadSolutionAsync(string path)
21 {
22 await UiScheduler.Default.InvokeAsync(() => Workspace.SolutionLoadError = "").ConfigureAwait(false);
23
24 try
25 {
26 var (root, normalizedSolutionPath, error, workspaceLoadVersion) =
27 await Workspace.LoadSolutionTreeAsync(path).ConfigureAwait(false);
28
29 await UiScheduler.Default.InvokeAsync(() =>
30 {
31 if (workspaceLoadVersion != Workspace.CurrentLoadVersion)
32 return;
33
34 if (root is null)
35 {
36 Workspace.SolutionLoadError = error ?? "Не удалось загрузить решение.";
37 return;
38 }
39
40 SolutionLoadSessionApplyProjection.ApplySuccessfulLoad(
41 Workspace,
42 root,
43 path,
44 normalizedSolutionPath,
45 IsDockedMfdSolutionExplorerTree,
46 EffectivePresentationTier,
47 this);
48 });
49 }
50 catch (Exception ex)
51 {
52 await UiScheduler.Default.InvokeAsync(() =>
53 Workspace.SolutionLoadError = "Ошибка загрузки решения: " + ex.Message);
54 SolutionLoadCrashLog.TryAppend(path, ex);
55 }
56 }
57
58 /// <summary>Пустое решение через <c>dotnet new sln</c> по полному пути к будущему <c>.sln</c> (файл не должен существовать).</summary>
59 public Task<BlankSolutionCreateResult> TryCreateBlankSolutionAtPathAsync(
60 string solutionFilePath,
61 CancellationToken cancellationToken = default) =>
62 BlankSolutionCreator.TryCreateAsync(solutionFilePath, _dotnetRunner, cancellationToken);
63
64 /// <summary><c>dotnet new</c> + <c>dotnet sln add</c> в текущее решение (ADR 0125).</summary>
65 public async Task<string> TryCreateProjectInSolutionAsync(
66 string template,
67 string projectName,
68 CancellationToken cancellationToken = default)
69 {
70 var result = await ProjectInSolutionCreator.TryCreateAsync(
71 Workspace.SolutionPath,
72 template,
73 projectName,
74 _dotnetRunner,
75 cancellationToken)
76 .ConfigureAwait(false);
77
78 if (!result.Ok)
79 return result.ErrorMessage ?? "Не удалось создать проект.";
80
81 if (!string.IsNullOrWhiteSpace(Workspace.SolutionPath))
82 await LoadSolutionAsync(Workspace.SolutionPath).ConfigureAwait(false);
83
84 return System.Text.Json.JsonSerializer.Serialize(
85 new { ok = true, project_path = result.ProjectPath },
86 new System.Text.Json.JsonSerializerOptions(System.Text.Json.JsonSerializerDefaults.Web));
87 }
88
89 [RelayCommand(CanExecute = nameof(CanInstallModel))]
90 private async Task InstallModelAsync()
91 {
92 var model = ModelToInstall?.Trim() ?? "";
93 if (string.IsNullOrEmpty(model) || !OllamaAvailable)
94 return;
95
96 IsPullingModel = true;
97 PullModelProgress = $"Скачивание {model}…";
98
99 try
100 {
101 await foreach (var status in _ollama.PullModelAsync(model, CancellationToken.None))
102 {
103 var s = status;
104 UiScheduler.Default.Post(() => PullModelProgress = s);
105 }
106 // IAsyncEnumerable после цикла может продолжиться не на UI — как у сборки без нужного контекста.
107 await UiScheduler.Default.InvokeAsync(async () =>
108 {
109 PullModelProgress = "Готово.";
110 await RefreshOllamaAsync();
111 });
112 }
113 catch (Exception ex)
114 {
115 await UiScheduler.Default.InvokeAsync(() =>
116 PullModelProgress = "Ошибка: " + ex.Message);
117 }
118 finally
119 {
120 await UiScheduler.Default.InvokeAsync(() => IsPullingModel = false);
121 }
122 }
123
124 private bool CanInstallModel() => OllamaAvailable && !string.IsNullOrWhiteSpace(ModelToInstall) && !IsPullingModel;
125
126 void SolutionLoadSessionApplyProjection.IHost.ResetEditorSessionForNewSolution()
127 {
128 _openFileDebounceCts?.Cancel();
129 Documents.ClearForNewSolution();
130 CurrentFilePath = null;
131 EditorText = "";
132 IsLoadingCurrentFile = false;
133 }
134
135 void SolutionLoadSessionApplyProjection.IHost.AfterSolutionApplied(MfdShellPage initialMfdPage)
136 {
137 InvalidateWorkspaceFileIndex();
138 RefreshSolutionExplorerTreeFilter();
139 RefreshStartupProjectAfterSolutionLoad();
140 TryNavigateToMfdShellPage(initialMfdPage);
141 ScheduleWorkspaceNavigationMapRefresh();
142 }
143}
View only · write via MCP/CIDE