From 36eae54bb0bfa18e291c990886fb102d368ad8db Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Mon, 14 Mar 2022 06:40:12 -0600 Subject: [PATCH] Add BrowserView --- Wabbajack.App.Wpf/Messages/OpenBrowserTab.cs | 11 +++ .../View Models/BrowserTabViewModel.cs | 90 +++++++++++++++++++ Wabbajack.App.Wpf/Views/BrowserTabView.xaml | 23 +++++ .../Views/BrowserTabView.xaml.cs | 51 +++++++++++ Wabbajack.App.Wpf/Views/BrowserView.xaml | 34 +++++++ Wabbajack.App.Wpf/Views/BrowserView.xaml.cs | 13 +++ Wabbajack.App.Wpf/Views/MainWindow.xaml.cs | 8 ++ 7 files changed, 230 insertions(+) create mode 100644 Wabbajack.App.Wpf/Messages/OpenBrowserTab.cs create mode 100644 Wabbajack.App.Wpf/View Models/BrowserTabViewModel.cs create mode 100644 Wabbajack.App.Wpf/Views/BrowserTabView.xaml create mode 100644 Wabbajack.App.Wpf/Views/BrowserTabView.xaml.cs create mode 100644 Wabbajack.App.Wpf/Views/BrowserView.xaml create mode 100644 Wabbajack.App.Wpf/Views/BrowserView.xaml.cs diff --git a/Wabbajack.App.Wpf/Messages/OpenBrowserTab.cs b/Wabbajack.App.Wpf/Messages/OpenBrowserTab.cs new file mode 100644 index 00000000..b0160a1e --- /dev/null +++ b/Wabbajack.App.Wpf/Messages/OpenBrowserTab.cs @@ -0,0 +1,11 @@ +namespace Wabbajack.Messages; + +public class OpenBrowserTab +{ + public BrowserTabViewModel ViewModel { get; set; } + + public OpenBrowserTab(BrowserTabViewModel viewModel) + { + ViewModel = viewModel; + } +} \ No newline at end of file diff --git a/Wabbajack.App.Wpf/View Models/BrowserTabViewModel.cs b/Wabbajack.App.Wpf/View Models/BrowserTabViewModel.cs new file mode 100644 index 00000000..aa8b964c --- /dev/null +++ b/Wabbajack.App.Wpf/View Models/BrowserTabViewModel.cs @@ -0,0 +1,90 @@ +using System; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using HtmlAgilityPack; +using Microsoft.Web.WebView2.Core; +using Microsoft.Web.WebView2.Wpf; +using ReactiveUI.Fody.Helpers; +using Wabbajack.DTOs.Logins; +using Wabbajack.Views; + +namespace Wabbajack; + +public abstract class BrowserTabViewModel : ViewModel +{ + [Reactive] public string HeaderText { get; set; } + + [Reactive] public string Instructions { get; set; } + + public BrowserView? Browser { get; set; } + + private WebView2 _browser => Browser!.Browser; + + public async Task RunWrapper(CancellationToken token) + { + await Run(token); + } + + protected abstract Task Run(CancellationToken token); + + protected async Task WaitForReady() + { + while (Browser?.Browser.CoreWebView2 == null) + { + await Task.Delay(250); + } + } + + public async Task NavigateTo(Uri uri) + { + var tcs = new TaskCompletionSource(); + + void Completed(object? o, CoreWebView2NavigationCompletedEventArgs a) + { + if (a.IsSuccess) + { + tcs.TrySetResult(); + } + else + { + tcs.TrySetException(new Exception($"Navigation error to {uri}")); + } + } + + _browser.NavigationCompleted += Completed; + _browser.Source = uri; + await tcs.Task; + _browser.NavigationCompleted -= Completed; + } + + public async Task GetCookies(string domainEnding, CancellationToken token) + { + var cookies = (await _browser.CoreWebView2.CookieManager.GetCookiesAsync("")) + .Where(c => c.Domain.EndsWith(domainEnding)); + return cookies.Select(c => new Cookie + { + Domain = c.Domain, + Name = c.Name, + Path = c.Path, + Value = c.Value + }).ToArray(); + } + + public async Task EvaluateJavaScript(string js) + { + return await _browser.ExecuteScriptAsync(js); + } + + public async Task GetDom(CancellationToken token) + { + var v = HttpUtility.UrlDecode("\u003D"); + var source = await EvaluateJavaScript("document.body.outerHTML"); + var decoded = JsonSerializer.Deserialize(source); + var doc = new HtmlDocument(); + doc.LoadHtml(decoded); + return doc; + } +} \ No newline at end of file diff --git a/Wabbajack.App.Wpf/Views/BrowserTabView.xaml b/Wabbajack.App.Wpf/Views/BrowserTabView.xaml new file mode 100644 index 00000000..d6b9d8c4 --- /dev/null +++ b/Wabbajack.App.Wpf/Views/BrowserTabView.xaml @@ -0,0 +1,23 @@ + + + + + + + _ + + + + + + + + diff --git a/Wabbajack.App.Wpf/Views/BrowserTabView.xaml.cs b/Wabbajack.App.Wpf/Views/BrowserTabView.xaml.cs new file mode 100644 index 00000000..64a59d6e --- /dev/null +++ b/Wabbajack.App.Wpf/Views/BrowserTabView.xaml.cs @@ -0,0 +1,51 @@ +using System; +using System.Reactive.Disposables; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using ReactiveUI; +using Wabbajack.Common; + +namespace Wabbajack.Views; + +public partial class BrowserTabView : IDisposable +{ + private readonly CompositeDisposable _compositeDisposable; + + public BrowserTabView(BrowserTabViewModel vm) + { + _compositeDisposable = new CompositeDisposable(); + InitializeComponent(); + Browser.Browser.Source = new Uri("http://www.google.com"); + vm.Browser = Browser; + DataContext = vm; + + vm.WhenAnyValue(vm => vm.HeaderText) + .BindTo(this, view => view.HeaderText.Text) + .DisposeWith(_compositeDisposable); + + Start().FireAndForget(); + } + + private async Task Start() + { + await ((BrowserTabViewModel) DataContext).RunWrapper(CancellationToken.None); + ClickClose(this, new RoutedEventArgs()); + } + + public void Dispose() + { + _compositeDisposable.Dispose(); + var vm = (BrowserTabViewModel) DataContext; + vm.Browser = null; + } + + private void ClickClose(object sender, RoutedEventArgs e) + { + var tc = (TabControl) this.Parent; + tc.Items.Remove(this); + this.Dispose(); + } +} + diff --git a/Wabbajack.App.Wpf/Views/BrowserView.xaml b/Wabbajack.App.Wpf/Views/BrowserView.xaml new file mode 100644 index 00000000..b4de535e --- /dev/null +++ b/Wabbajack.App.Wpf/Views/BrowserView.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Wabbajack.App.Wpf/Views/BrowserView.xaml.cs b/Wabbajack.App.Wpf/Views/BrowserView.xaml.cs new file mode 100644 index 00000000..3a88cb24 --- /dev/null +++ b/Wabbajack.App.Wpf/Views/BrowserView.xaml.cs @@ -0,0 +1,13 @@ +using System.Windows.Controls; +using ReactiveUI; + +namespace Wabbajack.Views; + +public partial class BrowserView +{ + public BrowserView() + { + InitializeComponent(); + } +} + diff --git a/Wabbajack.App.Wpf/Views/MainWindow.xaml.cs b/Wabbajack.App.Wpf/Views/MainWindow.xaml.cs index d3ac4656..c49b23bc 100644 --- a/Wabbajack.App.Wpf/Views/MainWindow.xaml.cs +++ b/Wabbajack.App.Wpf/Views/MainWindow.xaml.cs @@ -11,6 +11,7 @@ using Wabbajack.Common; using Wabbajack.Messages; using Wabbajack.Paths.IO; using Wabbajack.Util; +using Wabbajack.Views; namespace Wabbajack { @@ -188,5 +189,12 @@ namespace Wabbajack { this.DragMove(); } + + private void OnOpenBrowserTab(OpenBrowserTab msg) + { + var tab = new BrowserTabView(msg.ViewModel); + Tabs.Items.Add(tab); + Tabs.SelectedItem = tab; + } } }