feat: improve UI/UX of font loading

This commit is contained in:
ema
2025-09-08 01:14:01 +08:00
parent cddf767c6c
commit 07debda5e4
3 changed files with 50 additions and 2 deletions

View File

@@ -0,0 +1,26 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace QuickLook.Plugin.FontViewer;
public class ObservableFileStream(string path, FileMode mode, FileAccess access, FileShare share) : FileStream(path, mode, access, share)
{
public bool IsEndOfStream { get; protected set; } = false;
public override int Read(byte[] array, int offset, int count)
{
int result = base.Read(array, offset, count);
if (result == 0)
IsEndOfStream = true;
return result;
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
int result = await base.ReadAsync(buffer, offset, count, cancellationToken);
if (result == 0)
IsEndOfStream = true;
return result;
}
}

View File

@@ -19,6 +19,7 @@ using QuickLook.Common.Plugin;
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
namespace QuickLook.Plugin.FontViewer; namespace QuickLook.Plugin.FontViewer;
@@ -52,7 +53,12 @@ public class Plugin : IViewer
context.ViewerContent = _panel; context.ViewerContent = _panel;
context.Title = Path.GetFileName(path); context.Title = Path.GetFileName(path);
_ = Task.Run(() =>
{
_ = _panel.WaitForFontSent();
context.IsBusy = false; context.IsBusy = false;
});
} }
public void Cleanup() public void Cleanup()

View File

@@ -26,6 +26,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Threading;
namespace QuickLook.Plugin.FontViewer; namespace QuickLook.Plugin.FontViewer;
@@ -34,6 +35,7 @@ public class WebfontPanel : WebpagePanel
protected const string _resourcePrefix = "QuickLook.Plugin.FontViewer.Resources."; protected const string _resourcePrefix = "QuickLook.Plugin.FontViewer.Resources.";
protected internal static readonly Dictionary<string, byte[]> _resources = []; protected internal static readonly Dictionary<string, byte[]> _resources = [];
protected byte[] _homePage; protected byte[] _homePage;
protected ObservableFileStream _fontStream = null;
static WebfontPanel() static WebfontPanel()
{ {
@@ -153,10 +155,11 @@ public class WebfontPanel : WebpagePanel
if (File.Exists(localPath)) if (File.Exists(localPath))
{ {
var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); var fileStream = new ObservableFileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse( var response = _webView.CoreWebView2.Environment.CreateWebResourceResponse(
fileStream, 200, "OK", MimeTypes.GetContentType()); fileStream, 200, "OK", MimeTypes.GetContentType());
args.Response = response; args.Response = response;
_fontStream = fileStream; // Only the font request will set this
} }
} }
} }
@@ -168,6 +171,19 @@ public class WebfontPanel : WebpagePanel
} }
} }
public bool WaitForFontSent()
{
bool timeout = SpinWait.SpinUntil(
() => _fontStream is not null && _fontStream.IsEndOfStream,
TimeSpan.FromSeconds(1.5d) // The prediction is MAX 100MB
);
// Only when the `IsEndOfStream` is true
// Delay 15ms per MB for webview2 to render the font
if (timeout) Thread.Sleep(15 * (int)(_fontStream.Position / 1_048_576));
return timeout;
}
public static bool ContainsKey(string key) public static bool ContainsKey(string key)
{ {
return _resources.ContainsKey(key); return _resources.ContainsKey(key);