重写webview3

This commit is contained in:
rmbgame
2021-06-10 21:01:39 +08:00
parent 3c65d716b1
commit 288f947730
14 changed files with 187 additions and 151 deletions
@@ -0,0 +1,18 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls"
x:Class="System.Application.UI.Views.Controls.WebView3">
<Panel HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<controls:WebViewBase x:Name="Browser"
Background="Transparent"/>
<controls:ProgressRing x:Name="webViewLoading"
IsIndeterminate="True"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="100" Width="100" />
</Panel>
</UserControl>
@@ -0,0 +1,106 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using CefNet;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
namespace System.Application.UI.Views.Controls
{
public partial class WebView3 : UserControl, IDisposable
{
readonly ProgressRing webViewLoading;
bool disposedValue;
public WebViewBase Browser { get; }
/// <summary>
/// webview url <see cref="TextGap"/> property.
/// </summary>
public static readonly StyledProperty<string> UrlProperty =
AvaloniaProperty.Register<ScrollingTextBlock, string>(nameof(Url), WebView3WindowViewModel.AboutBlank);
public string Url
{
get { return GetValue(UrlProperty); }
set { SetValue(UrlProperty, value); }
}
public WebView3()
{
InitializeComponent();
webViewLoading = this.FindControl<ProgressRing>(nameof(webViewLoading));
Browser = this.FindControl<WebViewBase>(nameof(Browser));
Browser.Opacity = 0;
Browser.LoadingStateChange += WebView_LoadingStateChange;
this.GetObservable(UrlProperty)
.Subscribe(x =>
{
Navigate(Url);
});
}
public void Navigate(string url)
{
if (Browser.BrowserObject == null)
{
Browser.InitialUrl = url;
}
else
{
Browser.Navigate(url);
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void WebView_LoadingStateChange(object? sender, LoadingStateChangeEventArgs e)
{
if (!e.Busy)
{
if (Browser.Opacity != 1) Browser.Opacity = 1;
if (webViewLoading.IsVisible) webViewLoading.IsVisible = false;
}
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
Dispose();
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
if (Browser != null)
{
Browser.LoadingStateChange -= WebView_LoadingStateChange;
((IDisposable)Browser).Dispose();
}
}
// TODO: 释放未托管的资源(未托管的对象)并替代终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}
public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
@@ -16,7 +16,7 @@ using static System.Application.Services.CloudService.Constants;
// ReSharper disable once CheckNamespace
namespace System.Application.UI.Views.Controls
{
public sealed class WebView3 : WebView
public class WebViewBase : WebView
{
public static readonly RoutedEvent<FullscreenModeChangeEventArgs> FullscreenEvent = RoutedEvent.Register<WebView, FullscreenModeChangeEventArgs>("Fullscreen", RoutingStrategies.Bubble);
@@ -26,11 +26,11 @@ namespace System.Application.UI.Views.Controls
remove { RemoveHandler(FullscreenEvent, value); }
}
public WebView3()
public WebViewBase()
{
}
public WebView3(WebView opener) : base(opener)
public WebViewBase(WebView opener) : base(opener)
{
}
@@ -87,7 +87,7 @@ namespace System.Application.UI.Views.Controls
public class FullscreenModeChangeEventArgs : RoutedEventArgs
{
public FullscreenModeChangeEventArgs(IInteractive source, bool fullscreen) : base(WebView3.FullscreenEvent, source)
public FullscreenModeChangeEventArgs(IInteractive source, bool fullscreen) : base(WebViewBase.FullscreenEvent, source)
{
Fullscreen = fullscreen;
}
@@ -100,14 +100,14 @@ namespace System.Application.UI.Views.Controls
const int SHOW_DEV_TOOLS = (int)CefMenuId.UserFirst + 0;
//const int INSPECT_ELEMENT = (int)CefMenuId.UserFirst + 1;
readonly WebView3 webView;
readonly WebViewBase webView;
public WebView3Glue(WebView3 view) : base(view)
public WebView3Glue(WebViewBase view) : base(view)
{
webView = view;
}
private new WebView3 WebView => (WebView3)base.WebView;
private new WebViewBase WebView => (WebViewBase)base.WebView;
protected override bool OnSetFocus(CefBrowser browser, CefFocusSource source)
{
@@ -332,11 +332,11 @@ namespace System.Application.UI.Views.Controls
/// </summary>
unsafe class StreamResponseFilter : CefResponseFilter
{
readonly WebView3 webView;
readonly WebViewBase webView;
readonly bool rspIsCiphertext;
MemoryStream? memoryStream;
public StreamResponseFilter(WebView3 webView, bool rspIsCiphertext)
public StreamResponseFilter(WebViewBase webView, bool rspIsCiphertext)
{
this.webView = webView;
this.rspIsCiphertext = rspIsCiphertext;
@@ -6,7 +6,6 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="System.Application.UI.Views.Pages.About_ChangeLog">
<Panel>
<controls:WebView3 x:Name="webViewQA" Background="Transparent" />
<controls:ProgressRing x:Name="webViewQALoading" IsIndeterminate="True" HorizontalAlignment="Stretch" Height="100" Width="100" />
<controls:WebView3 x:Name="webView" Background="Transparent" />
</Panel>
</UserControl>
@@ -8,71 +8,25 @@ using System.Application.UI.Views.Controls;
namespace System.Application.UI.Views.Pages
{
public class About_ChangeLog : UserControl, IDisposable
public class About_ChangeLog : UserControl
{
readonly WebView3 webViewQA;
readonly ProgressRing webViewQALoading;
bool disposedValue;
readonly WebView3 webView;
public About_ChangeLog()
{
InitializeComponent();
webViewQALoading = this.FindControl<ProgressRing>(nameof(webViewQALoading));
webViewQA = this.FindControl<WebView3>(nameof(webViewQA));
webViewQA.Opacity = 0;
webViewQA.LoadingStateChange += WebView_LoadingStateChange;
webViewQA.InitialUrl = string.Format(
webView = this.FindControl<WebView3>(nameof(webView));
webView.Url = string.Format(
"https://steampp.net/changelogbox?theme={0}&language={1}",
CefNetApp.GetTheme(),
R.Language);
}
private void WebView_LoadingStateChange(object? sender, LoadingStateChangeEventArgs e)
{
if (!e.Busy)
{
if (webViewQA.Opacity != 1) webViewQA.Opacity = 1;
if (webViewQALoading.IsVisible) webViewQALoading.IsVisible = false;
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
Dispose();
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
if (webViewQA != null)
{
webViewQA.LoadingStateChange -= WebView_LoadingStateChange;
((IDisposable)webViewQA).Dispose();
}
}
// TODO: 释放未托管的资源(未托管的对象)并替代终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}
public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
@@ -7,6 +7,5 @@
x:Class="System.Application.UI.Views.Pages.About_FAQPage">
<Panel>
<controls:WebView3 x:Name="webViewQA" Background="Transparent" />
<controls:ProgressRing x:Name="webViewQALoading" IsIndeterminate="True" HorizontalAlignment="Stretch" Height="100" Width="100" />
</Panel>
</UserControl>
@@ -8,71 +8,24 @@ using System.Application.UI.Views.Controls;
namespace System.Application.UI.Views.Pages
{
public class About_FAQPage : UserControl, IDisposable
public class About_FAQPage : UserControl
{
readonly WebView3 webViewQA;
readonly ProgressRing webViewQALoading;
bool disposedValue;
WebView3 webViewQA;
public About_FAQPage()
{
InitializeComponent();
webViewQALoading = this.FindControl<ProgressRing>(nameof(webViewQALoading));
webViewQA = this.FindControl<WebView3>(nameof(webViewQA));
webViewQA.Opacity = 0;
webViewQA.LoadingStateChange += WebView_LoadingStateChange;
webViewQA.InitialUrl = string.Format(
webViewQA = this.FindControl<WebView3>("webViewQA");
webViewQA.Url = string.Format(
"https://steampp.net/faqbox?theme={0}&language={1}",
CefNetApp.GetTheme(),
R.Language);
}
private void WebView_LoadingStateChange(object? sender, LoadingStateChangeEventArgs e)
{
if (!e.Busy)
{
if (webViewQA.Opacity != 1) webViewQA.Opacity = 1;
if (webViewQALoading.IsVisible) webViewQALoading.IsVisible = false;
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
Dispose();
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
if (webViewQA != null)
{
webViewQA.LoadingStateChange -= WebView_LoadingStateChange;
((IDisposable)webViewQA).Dispose();
}
}
// TODO: 释放未托管的资源(未托管的对象)并替代终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}
public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
@@ -11,5 +11,19 @@
x:DataType="vm:ArchiSteamFarmPlusPageViewModel"
x:CompileBindings="True"
x:Class="System.Application.UI.Views.Pages.ArchiSteamFarmPlusPage">
<TabControl TabStripPlacement="Left">
<TabItem Header="ASF控制台">
</TabItem>
<TabItem Header="ASF Web UI">
</TabItem>
<TabItem Header="Bot配置">
</TabItem>
<TabItem Header="ASF配置">
</TabItem>
</TabControl>
</UserControl>
@@ -9,7 +9,7 @@ namespace System.Application.UI.Views.Pages
{
public class DebugWebViewPage : UserControl, IDisposable
{
readonly WebView webView;
readonly WebView3 webView;
readonly TextBox urlTextBox;
public DebugWebViewPage()
@@ -17,7 +17,7 @@ namespace System.Application.UI.Views.Pages
InitializeComponent();
webView = this.FindControl<WebView3>("webView");
webView.InitialUrl = "chrome://version";
webView.Url = "chrome://version";
//webView.BrowserCreated += WebView_BrowserCreated;
urlTextBox = this.FindControl<TextBox>("urlTextBox");
@@ -62,21 +62,21 @@ namespace System.Application.UI.Views.Pages
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
// TODO: 释放托管状态(托管对象)
if (webView != null)
{
((IDisposable)webView).Dispose();
}
}
// TODO: 释放未托管的资源(未托管的对象)并替代终结器
// TODO: 将大型字段设置为 null
// TODO: 释放未托管的资源(未托管的对象)并替代终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}
public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
//GC.SuppressFinalize(this);
}
@@ -114,7 +114,7 @@ namespace Avalonia.Controls
else if (DI.Platform == System.Platform.Apple)
{
ExtendClientAreaChromeHints =
ExtendClientAreaChromeHints.SystemChrome;
ExtendClientAreaChromeHints.OSXThickTitleBar;
}
else
{
@@ -225,7 +225,7 @@ namespace Avalonia.Controls
else if (DI.Platform == System.Platform.Apple)
{
ExtendClientAreaChromeHints =
ExtendClientAreaChromeHints.SystemChrome;
ExtendClientAreaChromeHints.OSXThickTitleBar;
}
else
{
@@ -31,9 +31,9 @@
MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
<controls:WebView3 x:Name="webView"/>
<controls:ProgressRing IsIndeterminate="True" HorizontalAlignment="Stretch" Height="100" Width="100" IsVisible="{Binding IsLoading}" />
<controls:WebView3 x:Name="webView" Url="{Binding Url}"/>
<!--Toast-->
<controls:ToastMessage />
</Panel>
@@ -29,11 +29,10 @@ namespace System.Application.UI.Views.Windows
this.AttachDevTools();
#endif
webView = this.FindControl<WebView3>(nameof(webView));
webView.InitialUrl = WebView3WindowViewModel.AboutBlank;
webView.Opacity = 0;
webView.DocumentTitleChanged += WebView_DocumentTitleChanged;
webView.LoadingStateChange += WebView_LoadingStateChange;
webView.BrowserCreated += WebView_BrowserCreated;
webView.Browser.InitialUrl = WebView3WindowViewModel.AboutBlank;
webView.Browser.DocumentTitleChanged += WebView_DocumentTitleChanged;
webView.Browser.LoadingStateChange += WebView_LoadingStateChange;
webView.Browser.BrowserCreated += WebView_BrowserCreated;
}
CancellationTokenSource? cts;
@@ -58,7 +57,7 @@ namespace System.Application.UI.Views.Windows
}
if (isDelayed && vm.IsLoading)
{
webView.Stop();
webView.Browser.Stop();
await WebViewLoadingTimeoutAsync(vm);
}
}
@@ -106,7 +105,7 @@ namespace System.Application.UI.Views.Windows
}
if (!e.Busy)
{
var mainFrame = webView.GetMainFrame();
var mainFrame = webView.Browser.GetMainFrame();
if (mainFrame != null)
{
var mainFrameSource = await mainFrame.GetSourceAsync(default);
@@ -115,7 +114,6 @@ namespace System.Application.UI.Views.Windows
await WebViewLoadingTimeoutAsync(vm);
return;
}
if (webView.Opacity != 1) webView.Opacity = 1;
if (vm.IsLoading)
{
vm.IsLoading = false;
@@ -128,7 +126,7 @@ namespace System.Application.UI.Views.Windows
string? initialUrl;
private void WebView_BrowserCreated(object? sender, EventArgs e)
{
if (initialUrl != null && webView.BrowserObject != null)
if (initialUrl != null && webView.Browser.BrowserObject != null)
{
webView.Navigate(initialUrl);
}
@@ -136,7 +134,7 @@ namespace System.Application.UI.Views.Windows
void Navigate(string url)
{
if (webView.BrowserObject == null)
if (webView.Browser.BrowserObject == null)
{
initialUrl = url;
}
@@ -203,9 +201,9 @@ namespace System.Application.UI.Views.Windows
{
await LoginUsingSteamClientCookiesAsync();
if (loginUsingSteamClientState == LoginUsingSteamClientState.Success
&& webView.BrowserObject != null)
&& webView.Browser.BrowserObject != null)
{
webView.Reload();
webView.Browser.Reload();
}
}
@@ -218,7 +216,7 @@ namespace System.Application.UI.Views.Windows
vm.Close += Close;
if (!string.IsNullOrWhiteSpace(vm.Title))
{
webView.DocumentTitleChanged -= WebView_DocumentTitleChanged;
webView.Browser.DocumentTitleChanged -= WebView_DocumentTitleChanged;
}
if (vm.UseLoginUsingSteamClient)
{
@@ -249,10 +247,10 @@ namespace System.Application.UI.Views.Windows
Navigate(x);
}
}).AddTo(vm);
vm.WhenAnyValue(x => x.StreamResponseFilterUrls).Subscribe(x => webView.StreamResponseFilterUrls = x).AddTo(vm);
vm.WhenAnyValue(x => x.FixedSinglePage).Subscribe(x => webView.FixedSinglePage = x).AddTo(vm);
vm.WhenAnyValue(x => x.IsSecurity).Subscribe(x => webView.IsSecurity = x).AddTo(vm);
webView.OnStreamResponseFilterResourceLoadComplete += vm.OnStreamResponseFilterResourceLoadComplete;
vm.WhenAnyValue(x => x.StreamResponseFilterUrls).Subscribe(x => webView.Browser.StreamResponseFilterUrls = x).AddTo(vm);
vm.WhenAnyValue(x => x.FixedSinglePage).Subscribe(x => webView.Browser.FixedSinglePage = x).AddTo(vm);
vm.WhenAnyValue(x => x.IsSecurity).Subscribe(x => webView.Browser.IsSecurity = x).AddTo(vm);
webView.Browser.OnStreamResponseFilterResourceLoadComplete += vm.OnStreamResponseFilterResourceLoadComplete;
}
}
@@ -302,11 +300,11 @@ namespace System.Application.UI.Views.Windows
if (webView != null)
{
cts?.Cancel();
webView.DocumentTitleChanged -= WebView_DocumentTitleChanged;
webView.LoadingStateChange -= WebView_LoadingStateChange;
webView.Browser.DocumentTitleChanged -= WebView_DocumentTitleChanged;
webView.Browser.LoadingStateChange -= WebView_LoadingStateChange;
if (DataContext is WebView3WindowViewModel vm)
{
webView.OnStreamResponseFilterResourceLoadComplete -= vm.OnStreamResponseFilterResourceLoadComplete;
webView.Browser.OnStreamResponseFilterResourceLoadComplete -= vm.OnStreamResponseFilterResourceLoadComplete;
}
((IDisposable)webView).Dispose();
}
@@ -57,9 +57,4 @@
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.999-cibuild0014488-beta" />
</ItemGroup>
<ItemGroup>
<Compile Update="Application\UI\Views\Pages\ArchiSteamFarmPlusPage.axaml.cs">
<DependentUpon>ArchiSteamFarmPlusPage.axaml</DependentUpon>
</Compile>
</ItemGroup>
</Project>
@@ -75,8 +75,8 @@ namespace System.Application.UI.ViewModels
AddTabItem<SteamAccountPageViewModel>();
AddTabItem<GameListPageViewModel>();
AddTabItem<LocalAuthPageViewModel>();
AddTabItem<ArchiSteamFarmPlusPageViewModel>();
//AddTabItem<SteamIdlePageViewModel>();
//AddTabItem<ArchiSteamFarmPlusPageViewModel>();
if (DI.Platform == Platform.Windows)
AddTabItem<GameRelatedPageViewModel>();
//AddTabItem<OtherPlatformPageViewModel>();