Skip to content

Commit

Permalink
Avoid recreating IMarkdownPreview control (#6153)
Browse files Browse the repository at this point in the history
* Avoid recreating markdown control

* Remove MarkdownPreview depdency property

* Pass IMarkdownPreview into the viewmodel instead of building it there

* Add missing using statement

* fix merge

* Move to singleton

* Remove creating instance in tab control

* pr comment
  • Loading branch information
jgonz120 authored Dec 11, 2024
1 parent acc521c commit ece3bfe
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.VisualStudio.Markdown.Platform;

namespace NuGet.PackageManagement.UI
{
public class MarkdownPreviewSingleton
{
#pragma warning disable CS0618 // Type or member is obsolete
private static IMarkdownPreview Instance;
#pragma warning restore CS0618 // Type or member is obsolete

#pragma warning disable CS0618 // Type or member is obsolete
public static IMarkdownPreview GetInstance()
#pragma warning restore CS0618 // Type or member is obsolete
{
if (Instance == null)
{
#pragma warning disable CS0618 // Type or member is obsolete
Instance = new PreviewBuilder().Build();
#pragma warning restore CS0618 // Type or member is obsolete
}

return Instance;
}

public static void ResetInstance()
{
if (Instance != null)
{
Instance.Dispose();
Instance = null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ public async Task InitializeAsync(DetailControlModel detailControlModel, INuGetP
{
var nuGetFeatureFlagService = await ServiceLocator.GetComponentModelServiceAsync<INuGetFeatureFlagService>();
_readmeTabEnabled = await nuGetFeatureFlagService.IsFeatureEnabledAsync(NuGetFeatureFlagConstants.RenderReadmeInPMUI);

#pragma warning disable CS0618 // Type or member is obsolete
ReadmePreviewViewModel = new ReadmePreviewViewModel(nugetPackageFileService, currentFilter, _readmeTabEnabled);
#pragma warning restore CS0618 // Type or member is obsolete
DetailControlModel = detailControlModel;

if (_readmeTabEnabled)
Expand Down Expand Up @@ -76,7 +77,6 @@ public void Dispose()
}
_disposed = true;
DetailControlModel.PropertyChanged -= DetailControlModel_PropertyChanged;

foreach (var tab in Tabs)
{
tab.PropertyChanged -= IsVisible_PropertyChanged;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ public sealed class ReadmePreviewViewModel : TitledPageViewModelBase
private bool _canRenderLocalReadme;
private bool _isBusy;

#pragma warning disable CS0618 // Type or member is obsolete
public ReadmePreviewViewModel(INuGetPackageFileService packageFileService, ItemFilter itemFilter, bool isReadmeFeatureEnabled)
#pragma warning restore CS0618 // Type or member is obsolete
{
_nugetPackageFileService = packageFileService ?? throw new ArgumentNullException(nameof(packageFileService));
_canRenderLocalReadme = CanRenderLocalReadme(itemFilter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ public void Refresh()
}).PostOnFailure(nameof(DetailControl));
}

public void Cleanup()
{
_packageDetailsTabControl.Dispose();
}

private void ProjectInstallButtonClicked(object sender, EventArgs e)
{
var model = (PackageDetailControlModel)DataContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ protected virtual void Dispose(bool disposing)
if (disposing)
{
PackageDetailsTabViewModel.Dispose();
MarkdownPreviewSingleton.ResetInstance();
}
_disposed = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,7 @@ private void CleanUp()
_refreshCts?.Dispose();
_cancelSelectionChangedSource?.Dispose();

_packageDetail.Cleanup();
_detailModel.Dispose();
_packageList.SelectionChanged -= PackageList_SelectionChanged;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@
<Grid>
<ContentControl
x:Name="descriptionMarkdownPreview"
x:Uid="descriptionMarkdownPreview"
ClipToBounds="True"
Focusable="False"
Visibility="{Binding Path=IsReadmeReady, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}" />
Visibility="{Binding Path=IsReadmeReady, Mode=OneWay, FallbackValue=Collapsed, Converter={StaticResource BooleanToVisibilityConverter}}" />
<Grid
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="{Binding Path=IsBusy, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}" >
Visibility="{Binding Path=IsBusy, Mode=OneWay, FallbackValue=Visible, Converter={StaticResource BooleanToVisibilityConverter}}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
Expand Down Expand Up @@ -75,6 +74,6 @@
<TextBlock
TextWrapping="Wrap"
Text="{x:Static nuget:Resources.Error_UnableToLoadReadme}"
Visibility="{Binding Path=ErrorWithReadme, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}" />
Visibility="{Binding Path=ErrorWithReadme, Mode=OneWay, FallbackValue=Collapsed, Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Windows;
using System.Windows.Controls;
using Microsoft.VisualStudio.Markdown.Platform;
using Microsoft.VisualStudio.Shell;
using NuGet.PackageManagement.UI.ViewModels;
using NuGet.VisualStudio;
using NuGet.VisualStudio.Telemetry;
Expand All @@ -16,19 +17,17 @@ namespace NuGet.PackageManagement.UI
/// <summary>
/// Interaction logic for PackageReadmeControl.xaml
/// </summary>
public partial class PackageReadmeControl : UserControl, IDisposable
public partial class PackageReadmeControl : UserControl
{
#pragma warning disable CS0618 // Type or member is obsolete
private IMarkdownPreview _markdownPreview;
#pragma warning restore CS0618 // Type or member is obsolete
private bool _disposed = false;

public PackageReadmeControl()
{
InitializeComponent();
#pragma warning disable CS0618 // Type or member is obsolete
_markdownPreview = new PreviewBuilder().Build();
#pragma warning restore CS0618 // Type or member is obsolete
_markdownPreview = MarkdownPreviewSingleton.GetInstance();
descriptionMarkdownPreview.Content = _markdownPreview.VisualElement;
}

public ReadmePreviewViewModel ReadmeViewModel { get => (ReadmePreviewViewModel)DataContext; }
Expand All @@ -41,36 +40,10 @@ private void ReadmeViewModel_PropertyChanged(object sender, PropertyChangedEvent
}
}

public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}

if (disposing)
{
_markdownPreview?.Dispose();
if (ReadmeViewModel is not null)
{
ReadmeViewModel.PropertyChanged -= ReadmeViewModel_PropertyChanged;
}
}

_disposed = true;
}

private async Task UpdateMarkdownAsync()
{
try
{
descriptionMarkdownPreview.Content = descriptionMarkdownPreview.Content ?? _markdownPreview.VisualElement;
if (!string.IsNullOrWhiteSpace(ReadmeViewModel.ReadmeMarkdown))
{
await _markdownPreview.UpdateContentAsync(ReadmeViewModel.ReadmeMarkdown, ScrollHint.None);
Expand All @@ -88,6 +61,10 @@ private void UserControl_DataContextChanged(object sender, DependencyPropertyCha
{
if (e.OldValue is ReadmePreviewViewModel oldMetadata)
{
ThreadHelper.JoinableTaskFactory.Run(async () =>
{
await _markdownPreview.UpdateContentAsync("", ScrollHint.None);
});
oldMetadata.PropertyChanged -= ReadmeViewModel_PropertyChanged;
}
if (ReadmeViewModel is not null)
Expand All @@ -98,13 +75,19 @@ private void UserControl_DataContextChanged(object sender, DependencyPropertyCha

private void PackageReadmeControl_Unloaded(object sender, RoutedEventArgs e)
{
Dispose();
if (ReadmeViewModel is not null)
{
ThreadHelper.JoinableTaskFactory.Run(async () =>
{
await _markdownPreview.UpdateContentAsync("", ScrollHint.None);
});
ReadmeViewModel.PropertyChanged -= ReadmeViewModel_PropertyChanged;
}
}

private void PackageReadmeControl_Loaded(object sender, RoutedEventArgs e)
{
NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(UpdateMarkdownAsync)
.PostOnFailure(nameof(PackageReadmeControl), nameof(PackageReadmeControl_Loaded));
NuGetUIThreadHelper.JoinableTaskFactory.Run(UpdateMarkdownAsync);
}
}
}

0 comments on commit ece3bfe

Please sign in to comment.