diff --git a/src/Common.CoreLib/Properties/ThisAssembly.cs b/src/Common.CoreLib/Properties/ThisAssembly.cs
index 9e788beac..9a4914d08 100644
--- a/src/Common.CoreLib/Properties/ThisAssembly.cs
+++ b/src/Common.CoreLib/Properties/ThisAssembly.cs
@@ -2,7 +2,7 @@ namespace System.Properties
{
public static class ThisAssembly
{
- public const string Version = "2.0.0.7";
+ public const string Version = "2.0.0.8";
public const string InfoVersion = Version + "-beta";
diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Controls/WebView3.cs b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Controls/WebView3.cs
index 29ffdf7f2..ad3494a4b 100644
--- a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Controls/WebView3.cs
+++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Controls/WebView3.cs
@@ -5,6 +5,8 @@ using CefNet.Internal;
using System.Application.Services.CloudService;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
+using System.Linq;
using static System.Application.Services.CloudService.Constants;
// ReSharper disable once CheckNamespace
@@ -43,7 +45,20 @@ namespace System.Application.UI.Views.Controls
RaiseEvent(e);
}
+ ///
+ /// 在浏览器中打开新窗口
+ ///
public bool OpenInBrowser { get; set; } = true;
+
+ ///
+ /// 需要拦截响应流的Url
+ ///
+ public string[]? StreamResponseFilterUrls { get; set; }
+
+ ///
+ /// 拦截响应流的处理
+ ///
+ public Action? OnStreamResponseFilterResourceLoadComplete { get; set; }
}
public class FullscreenModeChangeEventArgs : RoutedEventArgs
@@ -217,5 +232,104 @@ namespace System.Application.UI.Views.Controls
// var returnValue = base.OnBeforeResourceLoad(browser, frame, request, callback);
// return returnValue;
//}
+
+ protected override void OnResourceLoadComplete(CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response, CefUrlRequestStatus status, long receivedContentLength)
+ {
+ base.OnResourceLoadComplete(browser, frame, request, response, status, receivedContentLength);
+ if (responseDictionary.TryGetValue(request.Identifier, out var filter))
+ {
+ webView.OnStreamResponseFilterResourceLoadComplete?.Invoke(request.Url, filter.Data);
+ }
+ }
+
+ readonly Dictionary responseDictionary = new();
+
+ protected override CefResponseFilter GetResourceResponseFilter(CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response)
+ {
+ if (webView.StreamResponseFilterUrls != null && webView.StreamResponseFilterUrls.Contains(request.Url, StringComparer.OrdinalIgnoreCase))
+ {
+ var dataFilter = new StreamResponseFilter();
+ responseDictionary.Add(request.Identifier, dataFilter);
+ return dataFilter;
+ }
+ return base.GetResourceResponseFilter(browser, frame, request, response);
+ }
+
+ ///
+ /// https://stackoverflow.com/questions/45816851/using-cefsharp-to-capture-resource-response-data-body
+ ///
+ unsafe class StreamResponseFilter : CefResponseFilter
+ {
+ MemoryStream? memoryStream;
+
+ protected override bool InitFilter()
+ {
+ memoryStream = new();
+ return true;
+ }
+
+ protected override CefResponseFilterStatus Filter(IntPtr dataIn, long dataInSize, ref long dataInRead, IntPtr dataOut, long dataOutSize, ref long dataOutWritten)
+ {
+ Stream? dataInStream;
+ if (dataIn == default)
+ {
+ dataInStream = default;
+ }
+ else
+ {
+ var dataInBytePtr = (byte*)dataIn.ToPointer();
+ dataInStream = new UnmanagedMemoryStream(dataInBytePtr, dataInSize, dataInSize, FileAccess.Read);
+ }
+
+ var dataOutBytePtr = (byte*)dataOut.ToPointer();
+ UnmanagedMemoryStream dataOutStream = new(dataOutBytePtr, dataOutSize, dataOutSize, FileAccess.Write);
+
+ return Filter(dataInStream, dataInSize, ref dataInRead, dataOutStream, dataOutSize, ref dataOutWritten);
+ }
+
+ protected virtual CefResponseFilterStatus Filter(Stream? dataIn, long dataInSize, ref long dataInRead, Stream dataOut, long dataOutSize, ref long dataOutWritten)
+ {
+ if (dataIn == null)
+ {
+ dataInRead = 0;
+ dataOutWritten = 0;
+
+ return CefResponseFilterStatus.Done;
+ }
+
+ dataInRead = dataIn.Length;
+ dataOutWritten = Math.Min(dataInRead, dataOut.Length);
+
+ //Important we copy dataIn to dataOut
+ dataIn.CopyTo(dataOut);
+
+ //Copy data to stream
+ dataIn.Position = 0;
+ dataIn.CopyTo(memoryStream!);
+
+ return CefResponseFilterStatus.Done;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (!disposing)
+ {
+ if (disposing)
+ {
+ if (memoryStream != null)
+ {
+ memoryStream.Dispose();
+ memoryStream = null;
+ }
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ public byte[] Data
+ {
+ get { return memoryStream!.ToArray(); }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/WebView3Window.axaml.cs b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/WebView3Window.axaml.cs
index 2ad252e80..db4d5a0d1 100644
--- a/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/WebView3Window.axaml.cs
+++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Views/Windows/WebView3Window.axaml.cs
@@ -2,7 +2,6 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using CefNet;
-using CefNet.Avalonia;
using ReactiveUI;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
@@ -57,6 +56,11 @@ namespace System.Application.UI.Views.Windows
}
}
}).AddTo(vm);
+ vm.WhenAnyValue(x => x.StreamResponseFilterUrls).Subscribe(x =>
+ {
+ webView.StreamResponseFilterUrls = x;
+ }).AddTo(vm);
+ webView.OnStreamResponseFilterResourceLoadComplete += vm.OnStreamResponseFilterResourceLoadComplete;
}
}
@@ -92,6 +96,10 @@ namespace System.Application.UI.Views.Windows
// TODO: 释放托管状态(托管对象)
if (webView != null)
{
+ if (DataContext is WebView3WindowViewModel vm)
+ {
+ webView.OnStreamResponseFilterResourceLoadComplete -= vm.OnStreamResponseFilterResourceLoadComplete;
+ }
((IDisposable)webView).Dispose();
}
if (DataContext is IDisposable d)
diff --git a/src/ST.Client.Desktop.Avalonia/ST.Client.Desktop.Avalonia.csproj b/src/ST.Client.Desktop.Avalonia/ST.Client.Desktop.Avalonia.csproj
index b1454ae41..226aeec45 100644
--- a/src/ST.Client.Desktop.Avalonia/ST.Client.Desktop.Avalonia.csproj
+++ b/src/ST.Client.Desktop.Avalonia/ST.Client.Desktop.Avalonia.csproj
@@ -1,4 +1,4 @@
-
+
net5.0
@@ -6,6 +6,7 @@
false
System.Application.SteamTools.Client.Desktop.Avalonia
+ true
diff --git a/src/ST.Client.Desktop/UI/ViewModels/Windows/WebView3WindowViewModel.cs b/src/ST.Client.Desktop/UI/ViewModels/Windows/WebView3WindowViewModel.cs
index c04507395..764f3bc9a 100644
--- a/src/ST.Client.Desktop/UI/ViewModels/Windows/WebView3WindowViewModel.cs
+++ b/src/ST.Client.Desktop/UI/ViewModels/Windows/WebView3WindowViewModel.cs
@@ -12,5 +12,14 @@ namespace System.Application.UI.ViewModels
get => _Url;
set => this.RaiseAndSetIfChanged(ref _Url, value);
}
+
+ string[]? _StreamResponseFilterUrls;
+ public string[]? StreamResponseFilterUrls
+ {
+ get => _StreamResponseFilterUrls;
+ set => this.RaiseAndSetIfChanged(ref _StreamResponseFilterUrls, value);
+ }
+
+ public Action? OnStreamResponseFilterResourceLoadComplete { get; set; }
}
}
\ No newline at end of file
diff --git a/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs b/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs
index 9b88af271..f814143be 100644
--- a/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs
+++ b/src/ST.Client/Services/Implementation/AppUpdateServiceImpl.cs
@@ -315,7 +315,7 @@ namespace System.Application.Services.Implementation
break;
}
i++;
- OnReportDownloading3_(i / (float)incrementalUpdate.Count);
+ OnReportDownloading3_(i / (float)incrementalUpdate.Count * MaxProgressValue);
}
OnReport(MaxProgressValue);