mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 20:57:22 +02:00
Svg thumbnail failed rendering (#32936)
* [SVGThumbnail] Check fill-rule in SVG file and apply it. * [SVGThumbnail] Comment added * [SVGThumbnail] SvgContents is used instead of all html content. * [SVGThumbnail] - Use SvgContents to extract and modify SVG styles efficiently - Add retry logic and error handling for WebView2 initialization * use Linq --------- Co-authored-by: Jaime Bernardo <jaime@janeasystems.com> Co-authored-by: Leilei Zhang <leilzh@microsoft.com>
This commit is contained in:
@@ -5,8 +5,7 @@ using System.Drawing.Drawing2D;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
using Common.Utilities;
|
using Common.Utilities;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
using Microsoft.Web.WebView2.Core;
|
using Microsoft.Web.WebView2.Core;
|
||||||
@@ -118,10 +117,51 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Svg
|
|||||||
_browser.Height = (int)cx;
|
_browser.Height = (int)cx;
|
||||||
_browser.NavigationCompleted += async (object sender, CoreWebView2NavigationCompletedEventArgs args) =>
|
_browser.NavigationCompleted += async (object sender, CoreWebView2NavigationCompletedEventArgs args) =>
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check if the SVG element is present
|
||||||
var a = await _browser.ExecuteScriptAsync($"document.getElementsByTagName('svg')[0].viewBox;");
|
var a = await _browser.ExecuteScriptAsync($"document.getElementsByTagName('svg')[0].viewBox;");
|
||||||
if (a != null)
|
if (a != null)
|
||||||
{
|
{
|
||||||
await _browser.ExecuteScriptAsync($"document.getElementsByTagName('svg')[0].style = 'width:100%;height:100%';");
|
var svgContent = SvgContents.Substring(SvgContents.IndexOf("<svg", StringComparison.OrdinalIgnoreCase), SvgContents.IndexOf("</svg>", StringComparison.OrdinalIgnoreCase) - SvgContents.IndexOf("<svg", StringComparison.OrdinalIgnoreCase) + "</svg>".Length);
|
||||||
|
|
||||||
|
Dictionary<string, string> styleDict = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
// Try to parse the SVG content
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Attempt to parse the svgContent
|
||||||
|
var svgDocument = XDocument.Parse(svgContent);
|
||||||
|
var svgElement = svgDocument.Root;
|
||||||
|
var currentStyle = svgElement?.Attribute("style")?.Value;
|
||||||
|
|
||||||
|
// If style attribute exists, preserve existing styles
|
||||||
|
if (!string.IsNullOrEmpty(currentStyle) && currentStyle != "null")
|
||||||
|
{
|
||||||
|
styleDict = currentStyle
|
||||||
|
.Split(';', StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(stylePart => stylePart.Split(':', 2, StringSplitOptions.TrimEntries))
|
||||||
|
.Where(styleKeyValue => styleKeyValue.Length == 2 && !string.IsNullOrEmpty(styleKeyValue[0]))
|
||||||
|
.ToDictionary(
|
||||||
|
styleKeyValue => styleKeyValue[0],
|
||||||
|
styleKeyValue => styleKeyValue[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Log the error if the SVG content is not valid or parsing fails
|
||||||
|
Logger.LogError($"Failed to parse SVG content: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add or replace width and height in the existing style
|
||||||
|
styleDict["width"] = "100%";
|
||||||
|
styleDict["height"] = "100%";
|
||||||
|
|
||||||
|
// Construct a single JavaScript string to set all properties
|
||||||
|
var styleScript = string.Join(";", styleDict.Select(kv => $"document.getElementsByTagName('svg')[0].style.setProperty('{kv.Key}', '{kv.Value}');"));
|
||||||
|
|
||||||
|
// Apply the new style attributes using the constructed script
|
||||||
|
await _browser.ExecuteScriptAsync(styleScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide scrollbar - fixes #18286
|
// Hide scrollbar - fixes #18286
|
||||||
@@ -142,6 +182,12 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Svg
|
|||||||
}
|
}
|
||||||
|
|
||||||
thumbnailDone.Set();
|
thumbnailDone.Set();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Error during NavigationCompleted: ", ex);
|
||||||
|
thumbnailDone.Set();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var webView2Options = new CoreWebView2EnvironmentOptions("--block-new-web-contents");
|
var webView2Options = new CoreWebView2EnvironmentOptions("--block-new-web-contents");
|
||||||
@@ -151,6 +197,8 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Svg
|
|||||||
.ConfigureAwait(true).GetAwaiter();
|
.ConfigureAwait(true).GetAwaiter();
|
||||||
|
|
||||||
webView2EnvironmentAwaiter.OnCompleted(async () =>
|
webView2EnvironmentAwaiter.OnCompleted(async () =>
|
||||||
|
{
|
||||||
|
for (int attempt = 0; attempt < 3; attempt++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -198,11 +246,21 @@ namespace Microsoft.PowerToys.ThumbnailHandler.Svg
|
|||||||
{
|
{
|
||||||
_browser.NavigateToString(SvgContents);
|
_browser.NavigateToString(SvgContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break; // Exit the retry loop if initialization succeeds
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError($"Initialization attempt {attempt} failed: {ex.Message}");
|
||||||
|
if (attempt == 2)
|
||||||
{
|
{
|
||||||
Logger.LogError($"Failed running webView2Environment completed for {FilePath} : ", ex);
|
Logger.LogError($"Failed running webView2Environment completed for {FilePath} : ", ex);
|
||||||
thumbnailDone.Set();
|
thumbnailDone.Set();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(1000); // Delay before retrying
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user