@@ -37,9 +37,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
3737 const auto args = e.Parameter ().as <Editor::NavigateToPageArgs>();
3838 _ViewModel = args.ViewModel ().as <Editor::ExtensionsViewModel>();
3939
40+ // The extensions are loaded asynchronously as a part of the VM ctor.
41+ // However, there's a chance that they aren't done loading yet.
42+ // Calling LoadExtensions() ensures they're loaded by the time we try to display them, and it won't do anything if they're already loaded.
4043 auto vmImpl = get_self<ExtensionsViewModel>(_ViewModel);
44+ vmImpl->LoadExtensions ();
4145 vmImpl->ExtensionPackageIdentifierTemplateSelector (_extensionPackageIdentifierTemplateSelector);
42- vmImpl->LazyLoadExtensions ();
4346
4447 BringIntoViewWhenLoaded (args.ElementToFocus ());
4548
@@ -94,10 +97,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
9497
9598 ExtensionsViewModel::ExtensionsViewModel (const Model::CascadiaSettings& settings, const Editor::ColorSchemesPageViewModel& colorSchemesPageVM) :
9699 _settings{ settings },
97- _colorSchemesPageVM{ colorSchemesPageVM },
98- _extensionsLoaded{ false }
100+ _colorSchemesPageVM{ colorSchemesPageVM }
99101 {
100102 UpdateSettings (settings, colorSchemesPageVM);
103+ _LoadExtensionsAsync ();
101104
102105 PropertyChanged ([this ](auto &&, const PropertyChangedEventArgs& args) {
103106 const auto viewModelProperty{ args.PropertyName () };
@@ -217,7 +220,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
217220 _CurrentExtensionPackage = nullptr ;
218221
219222 // The extension packages may not be loaded yet because we want to wait until we actually navigate to the page to do so.
220- // In that case, omit "updating" them. They'll get the proper references when we lazy load them.
223+ // In that case, omit "updating" them. They'll get the proper references when we load them.
221224 if (_extensionPackages)
222225 {
223226 for (const auto & extPkg : _extensionPackages)
@@ -227,139 +230,146 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
227230 }
228231 }
229232
230- void ExtensionsViewModel::LazyLoadExtensions ()
233+ safe_void_coroutine ExtensionsViewModel::_LoadExtensionsAsync ()
231234 {
232- if (_extensionsLoaded)
235+ auto weakThis = get_weak ();
236+ co_await winrt::resume_background ();
237+ if (auto strongThis = weakThis.get ())
233238 {
234- return ;
239+ strongThis-> LoadExtensions () ;
235240 }
236- std::vector<Model::ExtensionPackage> extensions = wil::to_vector (_settings. Extensions ());
241+ }
237242
238- // these vectors track components all extensions successfully added
239- std::vector<Editor::ExtensionPackageViewModel> extensionPackages;
240- std::vector<Editor::FragmentProfileViewModel> profilesModifiedTotal;
241- std::vector<Editor::FragmentProfileViewModel> profilesAddedTotal;
242- std::vector<Editor::FragmentColorSchemeViewModel> colorSchemesAddedTotal;
243- for (const auto & extPkg : extensions)
244- {
245- auto extPkgVM = winrt::make_self<ExtensionPackageViewModel>(extPkg, _settings);
246- for (const auto & fragExt : extPkg.FragmentsView ())
243+ void ExtensionsViewModel::LoadExtensions ()
244+ {
245+ std::call_once (_extensionsLoaded, [this ]() {
246+ std::vector<Model::ExtensionPackage> extensions = wil::to_vector (_settings.Extensions ());
247+
248+ // these vectors track components all extensions successfully added
249+ std::vector<Editor::ExtensionPackageViewModel> extensionPackages;
250+ std::vector<Editor::FragmentProfileViewModel> profilesModifiedTotal;
251+ std::vector<Editor::FragmentProfileViewModel> profilesAddedTotal;
252+ std::vector<Editor::FragmentColorSchemeViewModel> colorSchemesAddedTotal;
253+ for (const auto & extPkg : extensions)
247254 {
248- const auto extensionEnabled = GetExtensionState (fragExt.Source (), _settings);
255+ auto extPkgVM = winrt::make_self<ExtensionPackageViewModel>(extPkg, _settings);
256+ for (const auto & fragExt : extPkg.FragmentsView ())
257+ {
258+ const auto extensionEnabled = GetExtensionState (fragExt.Source (), _settings);
249259
250- // these vectors track everything the current extension attempted to bring in
251- std::vector<Editor::FragmentProfileViewModel> currentProfilesModified;
252- std::vector<Editor::FragmentProfileViewModel> currentProfilesAdded;
253- std::vector<Editor::FragmentColorSchemeViewModel> currentColorSchemesAdded;
260+ // these vectors track everything the current extension attempted to bring in
261+ std::vector<Editor::FragmentProfileViewModel> currentProfilesModified;
262+ std::vector<Editor::FragmentProfileViewModel> currentProfilesAdded;
263+ std::vector<Editor::FragmentColorSchemeViewModel> currentColorSchemesAdded;
254264
255- if (fragExt.ModifiedProfilesView ())
256- {
257- for (const auto && entry : fragExt.ModifiedProfilesView ())
265+ if (fragExt.ModifiedProfilesView ())
258266 {
259- // Ensure entry successfully modifies a profile before creating and registering the object
260- if (const auto & deducedProfile = _settings.FindProfile (entry.ProfileGuid ()))
267+ for (const auto && entry : fragExt.ModifiedProfilesView ())
261268 {
262- auto vm = winrt::make<FragmentProfileViewModel>(entry, fragExt, deducedProfile);
263- currentProfilesModified.push_back (vm);
264- if (extensionEnabled)
269+ // Ensure entry successfully modifies a profile before creating and registering the object
270+ if (const auto & deducedProfile = _settings.FindProfile (entry.ProfileGuid ()))
265271 {
266- profilesModifiedTotal.push_back (vm);
272+ auto vm = winrt::make<FragmentProfileViewModel>(entry, fragExt, deducedProfile);
273+ currentProfilesModified.push_back (vm);
274+ if (extensionEnabled)
275+ {
276+ profilesModifiedTotal.push_back (vm);
277+ }
267278 }
268279 }
269280 }
270- }
271281
272- if (fragExt.NewProfilesView ())
273- {
274- for (const auto && entry : fragExt.NewProfilesView ())
282+ if (fragExt.NewProfilesView ())
275283 {
276- // Ensure entry successfully points to a profile before creating and registering the object.
277- // The profile may have been removed by the user.
278- if (const auto & deducedProfile = _settings.FindProfile (entry.ProfileGuid ()))
284+ for (const auto && entry : fragExt.NewProfilesView ())
279285 {
280- auto vm = winrt::make<FragmentProfileViewModel>( entry, fragExt, deducedProfile);
281- currentProfilesAdded. push_back (vm);
282- if (extensionEnabled )
286+ // Ensure entry successfully points to a profile before creating and registering the object.
287+ // The profile may have been removed by the user.
288+ if (const auto & deducedProfile = _settings. FindProfile (entry. ProfileGuid ()) )
283289 {
284- profilesAddedTotal.push_back (vm);
290+ auto vm = winrt::make<FragmentProfileViewModel>(entry, fragExt, deducedProfile);
291+ currentProfilesAdded.push_back (vm);
292+ if (extensionEnabled)
293+ {
294+ profilesAddedTotal.push_back (vm);
295+ }
285296 }
286297 }
287298 }
288- }
289299
290- if (fragExt.ColorSchemesView ())
291- {
292- for (const auto && entry : fragExt.ColorSchemesView ())
300+ if (fragExt.ColorSchemesView ())
293301 {
294- for (const auto & schemeVM : _colorSchemesPageVM. AllColorSchemes ())
302+ for (const auto && entry : fragExt. ColorSchemesView ())
295303 {
296- if ( schemeVM. Name () == entry. ColorSchemeName ())
304+ for ( const auto & schemeVM : _colorSchemesPageVM. AllColorSchemes ())
297305 {
298- auto vm = winrt::make<FragmentColorSchemeViewModel>(entry, fragExt, schemeVM);
299- currentColorSchemesAdded.push_back (vm);
300- if (extensionEnabled)
306+ if (schemeVM.Name () == entry.ColorSchemeName ())
301307 {
302- colorSchemesAddedTotal.push_back (vm);
308+ auto vm = winrt::make<FragmentColorSchemeViewModel>(entry, fragExt, schemeVM);
309+ currentColorSchemesAdded.push_back (vm);
310+ if (extensionEnabled)
311+ {
312+ colorSchemesAddedTotal.push_back (vm);
313+ }
303314 }
304315 }
305316 }
306317 }
307- }
308318
309- // sort the lists linguistically for nicer presentation
310- std::sort (currentProfilesModified.begin (), currentProfilesModified.end (), FragmentProfileViewModel::SortAscending);
311- std::sort (currentProfilesAdded.begin (), currentProfilesAdded.end (), FragmentProfileViewModel::SortAscending);
312- std::sort (currentColorSchemesAdded.begin (), currentColorSchemesAdded.end (), FragmentColorSchemeViewModel::SortAscending);
319+ // sort the lists linguistically for nicer presentation
320+ std::sort (currentProfilesModified.begin (), currentProfilesModified.end (), FragmentProfileViewModel::SortAscending);
321+ std::sort (currentProfilesAdded.begin (), currentProfilesAdded.end (), FragmentProfileViewModel::SortAscending);
322+ std::sort (currentColorSchemesAdded.begin (), currentColorSchemesAdded.end (), FragmentColorSchemeViewModel::SortAscending);
313323
314- extPkgVM->FragmentExtensions ().Append (winrt::make<FragmentExtensionViewModel>(fragExt, currentProfilesModified, currentProfilesAdded, currentColorSchemesAdded));
315- extPkgVM->PropertyChanged ([&](const IInspectable& sender, const PropertyChangedEventArgs& args) {
316- const auto viewModelProperty{ args.PropertyName () };
317- if (viewModelProperty == L" Enabled" )
318- {
319- // If the extension was enabled/disabled,
320- // check if any of its fragments modified profiles, added profiles, or added color schemes.
321- // Only notify what was affected!
322- bool hasModifiedProfiles = false ;
323- bool hasAddedProfiles = false ;
324- bool hasAddedColorSchemes = false ;
325- for (const auto & fragExtVM : sender.as <ExtensionPackageViewModel>()->FragmentExtensions ())
324+ extPkgVM->FragmentExtensions ().Append (winrt::make<FragmentExtensionViewModel>(fragExt, currentProfilesModified, currentProfilesAdded, currentColorSchemesAdded));
325+ extPkgVM->PropertyChanged ([&](const IInspectable& sender, const PropertyChangedEventArgs& args) {
326+ const auto viewModelProperty{ args.PropertyName () };
327+ if (viewModelProperty == L" Enabled" )
326328 {
327- const auto profilesModified = fragExtVM.ProfilesModified ();
328- const auto profilesAdded = fragExtVM.ProfilesAdded ();
329- const auto colorSchemesAdded = fragExtVM.ColorSchemesAdded ();
330- hasModifiedProfiles |= profilesModified && profilesModified.Size () > 0 ;
331- hasAddedProfiles |= profilesAdded && profilesAdded.Size () > 0 ;
332- hasAddedColorSchemes |= colorSchemesAdded && colorSchemesAdded.Size () > 0 ;
333- }
334- if (hasModifiedProfiles)
335- {
336- _NotifyChanges (L" ProfilesModified" );
337- }
338- if (hasAddedProfiles)
339- {
340- _NotifyChanges (L" ProfilesAdded" );
341- }
342- if (hasAddedColorSchemes)
343- {
344- _NotifyChanges (L" ColorSchemesAdded" );
329+ // If the extension was enabled/disabled,
330+ // check if any of its fragments modified profiles, added profiles, or added color schemes.
331+ // Only notify what was affected!
332+ bool hasModifiedProfiles = false ;
333+ bool hasAddedProfiles = false ;
334+ bool hasAddedColorSchemes = false ;
335+ for (const auto & fragExtVM : sender.as <ExtensionPackageViewModel>()->FragmentExtensions ())
336+ {
337+ const auto profilesModified = fragExtVM.ProfilesModified ();
338+ const auto profilesAdded = fragExtVM.ProfilesAdded ();
339+ const auto colorSchemesAdded = fragExtVM.ColorSchemesAdded ();
340+ hasModifiedProfiles |= profilesModified && profilesModified.Size () > 0 ;
341+ hasAddedProfiles |= profilesAdded && profilesAdded.Size () > 0 ;
342+ hasAddedColorSchemes |= colorSchemesAdded && colorSchemesAdded.Size () > 0 ;
343+ }
344+ if (hasModifiedProfiles)
345+ {
346+ _NotifyChanges (L" ProfilesModified" );
347+ }
348+ if (hasAddedProfiles)
349+ {
350+ _NotifyChanges (L" ProfilesAdded" );
351+ }
352+ if (hasAddedColorSchemes)
353+ {
354+ _NotifyChanges (L" ColorSchemesAdded" );
355+ }
345356 }
346- }
347- });
357+ });
358+ }
359+ extensionPackages.push_back (*extPkgVM);
348360 }
349- extensionPackages.push_back (*extPkgVM);
350- }
351361
352- // sort the lists linguistically for nicer presentation
353- std::sort (extensionPackages.begin (), extensionPackages.end (), ExtensionPackageViewModel::SortAscending);
354- std::sort (profilesModifiedTotal.begin (), profilesModifiedTotal.end (), FragmentProfileViewModel::SortAscending);
355- std::sort (profilesAddedTotal.begin (), profilesAddedTotal.end (), FragmentProfileViewModel::SortAscending);
356- std::sort (colorSchemesAddedTotal.begin (), colorSchemesAddedTotal.end (), FragmentColorSchemeViewModel::SortAscending);
357-
358- _extensionPackages = single_threaded_observable_vector<Editor::ExtensionPackageViewModel>(std::move (extensionPackages));
359- _profilesModifiedView = single_threaded_observable_vector<Editor::FragmentProfileViewModel>(std::move (profilesModifiedTotal));
360- _profilesAddedView = single_threaded_observable_vector<Editor::FragmentProfileViewModel>(std::move (profilesAddedTotal));
361- _colorSchemesAddedView = single_threaded_observable_vector<Editor::FragmentColorSchemeViewModel>(std::move (colorSchemesAddedTotal));
362- _extensionsLoaded = true ;
362+ // sort the lists linguistically for nicer presentation
363+ std::sort (extensionPackages.begin (), extensionPackages.end (), ExtensionPackageViewModel::SortAscending);
364+ std::sort (profilesModifiedTotal.begin (), profilesModifiedTotal.end (), FragmentProfileViewModel::SortAscending);
365+ std::sort (profilesAddedTotal.begin (), profilesAddedTotal.end (), FragmentProfileViewModel::SortAscending);
366+ std::sort (colorSchemesAddedTotal.begin (), colorSchemesAddedTotal.end (), FragmentColorSchemeViewModel::SortAscending);
367+
368+ _extensionPackages = single_threaded_observable_vector<Editor::ExtensionPackageViewModel>(std::move (extensionPackages));
369+ _profilesModifiedView = single_threaded_observable_vector<Editor::FragmentProfileViewModel>(std::move (profilesModifiedTotal));
370+ _profilesAddedView = single_threaded_observable_vector<Editor::FragmentProfileViewModel>(std::move (profilesAddedTotal));
371+ _colorSchemesAddedView = single_threaded_observable_vector<Editor::FragmentColorSchemeViewModel>(std::move (colorSchemesAddedTotal));
372+ }) ;
363373 }
364374
365375 Windows::UI::Xaml::DataTemplate ExtensionsViewModel::CurrentExtensionPackageIdentifierTemplate () const
0 commit comments