mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Merge pull request #239 from wabbajack-tools/use-lib-cef
Use lib cef for nexus logins
This commit is contained in:
commit
419567d865
@ -17,6 +17,7 @@ using ICSharpCode.SharpZipLib.BZip2;
|
||||
using IniParser;
|
||||
using Newtonsoft.Json;
|
||||
using ReactiveUI;
|
||||
using Syroot.Windows.IO;
|
||||
using Wabbajack.Common.StatusFeed;
|
||||
using Wabbajack.Common.StatusFeed.Errors;
|
||||
using YamlDotNet.Serialization;
|
||||
@ -899,5 +900,28 @@ namespace Wabbajack.Common
|
||||
}
|
||||
p.WaitForExit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a file to JSON but in an encrypted format in the user's app local directory.
|
||||
/// The data will be encrypted so that it can only be read by this machine and this user.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="data"></param>
|
||||
public static void ToEcryptedJson<T>(this T data, string key)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(data.ToJSON());
|
||||
var encoded = ProtectedData.Protect(bytes, Encoding.UTF8.GetBytes(key), DataProtectionScope.LocalMachine);
|
||||
var path = Path.Combine(KnownFolders.LocalAppData.Path, "Wabbajack", key);
|
||||
File.WriteAllBytes(path, encoded);
|
||||
}
|
||||
|
||||
public static T FromEncryptedJson<T>(string key)
|
||||
{
|
||||
var path = Path.Combine(KnownFolders.LocalAppData.Path, "Wabbajack", key);
|
||||
var bytes = File.ReadAllBytes(path);
|
||||
var decoded = ProtectedData.Unprotect(bytes, Encoding.UTF8.GetBytes(key), DataProtectionScope.LocalMachine);
|
||||
return Encoding.UTF8.GetString(decoded).FromJSONString<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,12 +75,16 @@
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Syroot.KnownFolders">
|
||||
<HintPath>..\..\..\Users\tbald\.nuget\packages\syroot.windows.io.knownfolders\1.2.1\lib\net452\Syroot.KnownFolders.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Security" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@ -169,6 +173,9 @@
|
||||
<PackageReference Include="ReactiveUI">
|
||||
<Version>10.5.30</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Syroot.Windows.IO.KnownFolders">
|
||||
<Version>1.2.1</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Data.HashFunction.xxHash">
|
||||
<Version>2.0.0</Version>
|
||||
</PackageReference>
|
||||
|
81
Wabbajack.Lib/LibCefHelpers/Init.cs
Normal file
81
Wabbajack.Lib/LibCefHelpers/Init.cs
Normal file
@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Alphaleonis.Win32.Filesystem;
|
||||
using Wabbajack.Common;
|
||||
using Xilium.CefGlue;
|
||||
|
||||
namespace Wabbajack.Lib.LibCefHelpers
|
||||
{
|
||||
public static class Helpers
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// We bundle the cef libs inside the .exe, we need to extract them before loading any wpf code that requires them
|
||||
/// </summary>
|
||||
public static void ExtractLibs()
|
||||
{
|
||||
if (File.Exists("cefglue.7z") && File.Exists("libcef.dll")) return;
|
||||
|
||||
using (var fs = File.OpenWrite("cefglue.7z"))
|
||||
using (var rs = Assembly.GetExecutingAssembly().GetManifestResourceStream("Wabbajack.Lib.LibCefHelpers.cefglue.7z"))
|
||||
{
|
||||
rs.CopyTo(fs);
|
||||
Utils.Log("Extracting libCef files");
|
||||
}
|
||||
using (var wq = new WorkQueue(1))
|
||||
FileExtractor.ExtractAll(wq, "cefglue.7z", ".");
|
||||
|
||||
}
|
||||
public static async Task<Cookie[]> GetCookies(string domainEnding)
|
||||
{
|
||||
var manager = CefCookieManager.GetGlobal(null);
|
||||
var visitor = new CookieVisitor();
|
||||
if (!manager.VisitAllCookies(visitor))
|
||||
return new Cookie[0];
|
||||
var cc = await visitor.Task;
|
||||
|
||||
return (await visitor.Task).Where(c => c.Domain.EndsWith(domainEnding)).ToArray();
|
||||
}
|
||||
|
||||
private class CookieVisitor : CefCookieVisitor
|
||||
{
|
||||
TaskCompletionSource<List<Cookie>> _source = new TaskCompletionSource<List<Cookie>>();
|
||||
public Task<List<Cookie>> Task => _source.Task;
|
||||
|
||||
public List<Cookie> Cookies { get; } = new List<Cookie>();
|
||||
protected override bool Visit(CefCookie cookie, int count, int total, out bool delete)
|
||||
{
|
||||
Cookies.Add(new Cookie
|
||||
{
|
||||
Name = cookie.Name,
|
||||
Value = cookie.Value,
|
||||
Domain = cookie.Domain,
|
||||
Path = cookie.Path
|
||||
});
|
||||
if (count == total)
|
||||
_source.SetResult(Cookies);
|
||||
delete = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
_source.SetResult(Cookies);
|
||||
}
|
||||
}
|
||||
|
||||
public class Cookie
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string Domain { get; set; }
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
BIN
Wabbajack.Lib/LibCefHelpers/cefglue.7z
Normal file
BIN
Wabbajack.Lib/LibCefHelpers/cefglue.7z
Normal file
Binary file not shown.
@ -12,10 +12,16 @@ using System.Security.Authentication;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Documents;
|
||||
using Syroot.Windows.IO;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib.Downloaders;
|
||||
using Wabbajack.Lib.LibCefHelpers;
|
||||
using WebSocketSharp;
|
||||
using Xilium.CefGlue;
|
||||
using Xilium.CefGlue.Common;
|
||||
using Xilium.CefGlue.Common.Handlers;
|
||||
using Xilium.CefGlue.WPF;
|
||||
using static Wabbajack.Lib.NexusApi.NexusApiUtils;
|
||||
|
||||
namespace Wabbajack.Lib.NexusApi
|
||||
@ -66,25 +72,12 @@ namespace Wabbajack.Lib.NexusApi
|
||||
File.Delete(API_KEY_CACHE_FILE);
|
||||
}
|
||||
|
||||
var cacheFolder = Path.Combine(new KnownFolder(KnownFolderType.LocalAppData).Path, "Wabbajack");
|
||||
if (!Directory.Exists(cacheFolder))
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(cacheFolder);
|
||||
return Utils.FromEncryptedJson<string>("nexusapikey");
|
||||
}
|
||||
|
||||
var cacheFile = Path.Combine(cacheFolder, _additionalEntropy);
|
||||
if (File.Exists(cacheFile))
|
||||
catch (Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Encoding.UTF8.GetString(
|
||||
ProtectedData.Unprotect(File.ReadAllBytes(cacheFile),
|
||||
Encoding.UTF8.GetBytes(_additionalEntropy), DataProtectionScope.CurrentUser));
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
File.Delete(cacheFile);
|
||||
}
|
||||
}
|
||||
|
||||
var env_key = Environment.GetEnvironmentVariable("NEXUSAPIKEY");
|
||||
@ -93,35 +86,66 @@ namespace Wabbajack.Lib.NexusApi
|
||||
return env_key;
|
||||
}
|
||||
|
||||
// open a web socket to receive the api key
|
||||
var guid = Guid.NewGuid();
|
||||
var _websocket = new WebSocket("wss://sso.nexusmods.com")
|
||||
{
|
||||
SslConfiguration =
|
||||
{
|
||||
EnabledSslProtocols = SslProtocols.Tls12
|
||||
}
|
||||
};
|
||||
|
||||
var api_key = new TaskCompletionSource<string>();
|
||||
_websocket.OnMessage += (sender, msg) => { api_key.SetResult(msg.Data); };
|
||||
|
||||
_websocket.Connect();
|
||||
_websocket.Send("{\"id\": \"" + guid + "\", \"appid\": \"" + Consts.AppName + "\"}");
|
||||
|
||||
// open a web browser to get user permission
|
||||
Process.Start($"https://www.nexusmods.com/sso?id={guid}&application=" + Consts.AppName);
|
||||
|
||||
// get the api key from the socket and cache it
|
||||
api_key.Task.Wait();
|
||||
var result = api_key.Task.Result;
|
||||
File.WriteAllBytes(cacheFile, ProtectedData.Protect(Encoding.UTF8.GetBytes(result),
|
||||
Encoding.UTF8.GetBytes(_additionalEntropy), DataProtectionScope.CurrentUser));
|
||||
|
||||
var result = Utils.Log(new RequestNexusAuthorization()).Task.Result;
|
||||
result.ToEcryptedJson("nexusapikey");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class RefererHandler : RequestHandler
|
||||
{
|
||||
private string _referer;
|
||||
|
||||
public RefererHandler(string referer)
|
||||
{
|
||||
_referer = referer;
|
||||
}
|
||||
protected override bool OnBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request, bool userGesture, bool isRedirect)
|
||||
{
|
||||
base.OnBeforeBrowse(browser, frame, request, userGesture, isRedirect);
|
||||
if (request.ReferrerURL == null)
|
||||
request.SetReferrer(_referer, CefReferrerPolicy.Default);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> SetupNexusLogin(BaseCefBrowser browser, Action<string> updateStatus)
|
||||
{
|
||||
updateStatus("Please Log Into the Nexus");
|
||||
browser.Address = "https://users.nexusmods.com/auth/continue?client_id=nexus&redirect_uri=https://www.nexusmods.com/oauth/callback&response_type=code&referrer=//www.nexusmods.com";
|
||||
while (true)
|
||||
{
|
||||
var cookies = (await Helpers.GetCookies("nexusmods.com"));
|
||||
if (cookies.FirstOrDefault(c => c.Name == "member_id") != null)
|
||||
break;
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
|
||||
// open a web socket to receive the api key
|
||||
var guid = Guid.NewGuid();
|
||||
var _websocket = new WebSocket("wss://sso.nexusmods.com")
|
||||
{
|
||||
SslConfiguration =
|
||||
{
|
||||
EnabledSslProtocols = SslProtocols.Tls12
|
||||
}
|
||||
};
|
||||
|
||||
updateStatus("Please Authorize Wabbajack to Download Mods");
|
||||
var api_key = new TaskCompletionSource<string>();
|
||||
_websocket.OnMessage += (sender, msg) => { api_key.SetResult(msg.Data); };
|
||||
|
||||
_websocket.Connect();
|
||||
_websocket.Send("{\"id\": \"" + guid + "\", \"appid\": \"" + Consts.AppName + "\"}");
|
||||
await Task.Delay(1000);
|
||||
|
||||
// open a web browser to get user permission
|
||||
browser.Address = $"https://www.nexusmods.com/sso?id={guid}&application={Consts.AppName}";
|
||||
|
||||
return await api_key.Task;
|
||||
}
|
||||
|
||||
public UserStatus GetUserStatus()
|
||||
{
|
||||
var url = "https://api.nexusmods.com/v1/users/validate.json";
|
||||
|
27
Wabbajack.Lib/NexusApi/RequestNexusAuthorization.cs
Normal file
27
Wabbajack.Lib/NexusApi/RequestNexusAuthorization.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Wabbajack.Common.StatusFeed;
|
||||
|
||||
namespace Wabbajack.Lib.NexusApi
|
||||
{
|
||||
public class RequestNexusAuthorization : AStatusMessage, IUserIntervention
|
||||
{
|
||||
public override string ShortDescription => "Getting User's Nexus API Key";
|
||||
public override string ExtendedDescription { get; }
|
||||
|
||||
private readonly TaskCompletionSource<string> _source = new TaskCompletionSource<string>();
|
||||
public Task<string> Task => _source.Task;
|
||||
|
||||
public void Resume(string apikey)
|
||||
{
|
||||
_source.SetResult(apikey);
|
||||
}
|
||||
public void Cancel()
|
||||
{
|
||||
_source.SetCanceled();
|
||||
}
|
||||
}
|
||||
}
|
@ -117,6 +117,7 @@
|
||||
<Compile Include="CompilationSteps\PatchStockESMs.cs" />
|
||||
<Compile Include="CompilationSteps\Serialization.cs" />
|
||||
<Compile Include="Downloaders\SteamWorkshopDownloader.cs" />
|
||||
<Compile Include="LibCefHelpers\Init.cs" />
|
||||
<Compile Include="MO2Compiler.cs" />
|
||||
<Compile Include="Data.cs" />
|
||||
<Compile Include="Downloaders\AbstractDownloadState.cs" />
|
||||
@ -138,6 +139,7 @@
|
||||
<Compile Include="NexusApi\Dtos.cs" />
|
||||
<Compile Include="NexusApi\NexusApi.cs" />
|
||||
<Compile Include="NexusApi\NexusApiUtils.cs" />
|
||||
<Compile Include="NexusApi\RequestNexusAuthorization.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ReportBuilder.cs" />
|
||||
<Compile Include="StatusMessages\ConfirmUpdateOfExistingInstall.cs" />
|
||||
@ -156,6 +158,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<EmbeddedResource Include="LibCefHelpers\cefglue.7z" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(SolutionDir)\Compression.BSA\Compression.BSA.csproj">
|
||||
@ -181,6 +184,9 @@
|
||||
<PackageReference Include="AlphaFS">
|
||||
<Version>2.2.6</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CefGlue.Wpf">
|
||||
<Version>75.1.28</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Ceras">
|
||||
<Version>4.1.7</Version>
|
||||
</PackageReference>
|
||||
|
@ -2,6 +2,7 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib;
|
||||
using Wabbajack.Lib.LibCefHelpers;
|
||||
|
||||
namespace Wabbajack.Test
|
||||
{
|
||||
@ -13,6 +14,7 @@ namespace Wabbajack.Test
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
Helpers.ExtractLibs();
|
||||
Consts.TestMode = true;
|
||||
|
||||
utils = new TestUtils();
|
||||
|
@ -4,6 +4,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib;
|
||||
using Wabbajack.Lib.Downloaders;
|
||||
using Wabbajack.Lib.LibCefHelpers;
|
||||
using Wabbajack.Lib.NexusApi;
|
||||
using Wabbajack.Lib.Validation;
|
||||
using File = Alphaleonis.Win32.Filesystem.File;
|
||||
@ -16,6 +17,7 @@ namespace Wabbajack.Test
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Helpers.ExtractLibs();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -141,6 +141,9 @@
|
||||
<PackageReference Include="AlphaFS">
|
||||
<Version>2.2.6</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CefGlue.Wpf">
|
||||
<Version>75.1.28</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MSTest.TestAdapter">
|
||||
<Version>2.0.0</Version>
|
||||
</PackageReference>
|
||||
|
@ -4,6 +4,7 @@ using System.Reflection;
|
||||
using System.Windows;
|
||||
using MahApps.Metro;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Lib.LibCefHelpers;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
@ -14,7 +15,7 @@ namespace Wabbajack
|
||||
{
|
||||
public App()
|
||||
{
|
||||
// Initialization in MainWindow ctor
|
||||
Helpers.ExtractLibs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,10 +102,14 @@ namespace Wabbajack
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
_listBox.ScrollIntoView(e.NewItems[0]);
|
||||
_listBox.SelectedItem = e.NewItems[0];
|
||||
try
|
||||
{
|
||||
_listBox.ScrollIntoView(e.NewItems[0]);
|
||||
_listBox.SelectedItem = e.NewItems[0];
|
||||
}
|
||||
catch (ArgumentOutOfRangeException) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,13 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Common.StatusFeed;
|
||||
using Wabbajack.Lib;
|
||||
using Wabbajack.Lib.NexusApi;
|
||||
using Wabbajack.Lib.StatusMessages;
|
||||
|
||||
namespace Wabbajack
|
||||
@ -33,15 +36,19 @@ namespace Wabbajack
|
||||
public readonly Lazy<InstallerVM> Installer;
|
||||
public readonly Lazy<ModListGalleryVM> Gallery;
|
||||
public readonly ModeSelectionVM ModeSelectionVM;
|
||||
public readonly WebBrowserVM WebBrowserVM;
|
||||
public Dispatcher ViewDispatcher { get; set; }
|
||||
|
||||
public MainWindowVM(MainWindow mainWindow, MainSettings settings)
|
||||
{
|
||||
MainWindow = mainWindow;
|
||||
ViewDispatcher = MainWindow.Dispatcher;
|
||||
Settings = settings;
|
||||
Installer = new Lazy<InstallerVM>(() => new InstallerVM(this));
|
||||
Compiler = new Lazy<CompilerVM>(() => new CompilerVM(this));
|
||||
Gallery = new Lazy<ModListGalleryVM>(() => new ModListGalleryVM(this));
|
||||
ModeSelectionVM = new ModeSelectionVM(this);
|
||||
WebBrowserVM = new WebBrowserVM();
|
||||
|
||||
// Set up logging
|
||||
Utils.LogMessages
|
||||
@ -59,6 +66,10 @@ namespace Wabbajack
|
||||
.OfType<ConfirmUpdateOfExistingInstall>()
|
||||
.Subscribe(msg => ConfirmUpdate(msg));
|
||||
|
||||
Utils.LogMessages
|
||||
.OfType<RequestNexusAuthorization>()
|
||||
.Subscribe(HandleRequestNexusAuthorization);
|
||||
|
||||
if (IsStartingFromModlist(out var path))
|
||||
{
|
||||
Installer.Value.ModListLocation.TargetPath = path;
|
||||
@ -71,6 +82,38 @@ namespace Wabbajack
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleRequestNexusAuthorization(RequestNexusAuthorization msg)
|
||||
{
|
||||
ViewDispatcher.InvokeAsync(async () =>
|
||||
{
|
||||
var oldPane = ActivePane;
|
||||
var vm = new WebBrowserVM();
|
||||
ActivePane = vm;
|
||||
try
|
||||
{
|
||||
vm.BackCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
ActivePane = oldPane;
|
||||
msg.Cancel();
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
var key = await NexusApiClient.SetupNexusLogin(vm.Browser, m => vm.Instructions = m);
|
||||
msg.Resume(key);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
msg.Cancel();
|
||||
}
|
||||
ActivePane = oldPane;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void ConfirmUpdate(ConfirmUpdateOfExistingInstall msg)
|
||||
{
|
||||
var result = MessageBox.Show(msg.ExtendedDescription, msg.ShortDescription, MessageBoxButton.OKCancel);
|
||||
|
30
Wabbajack/View Models/WebBrowserVM.cs
Normal file
30
Wabbajack/View Models/WebBrowserVM.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.Lib;
|
||||
using Xilium.CefGlue.Common;
|
||||
using Xilium.CefGlue.WPF;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
public class WebBrowserVM : ViewModel
|
||||
{
|
||||
[Reactive]
|
||||
public string Instructions { get; set; }
|
||||
|
||||
public WpfCefBrowser Browser { get; }
|
||||
|
||||
[Reactive]
|
||||
public IReactiveCommand BackCommand { get; set; }
|
||||
public WebBrowserVM(string url = "http://www.wabbajack.org")
|
||||
{
|
||||
Browser = new WpfCefBrowser();
|
||||
Browser.Address = url;
|
||||
Instructions = "Wabbajack Web Browser";
|
||||
}
|
||||
}
|
||||
}
|
@ -33,6 +33,9 @@
|
||||
<DataTemplate DataType="{x:Type local:ModListGalleryVM}">
|
||||
<local:ModListGalleryView />
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type local:WebBrowserVM}">
|
||||
<local:WebBrowserView />
|
||||
</DataTemplate>
|
||||
</ContentPresenter.Resources>
|
||||
</ContentPresenter>
|
||||
</mahapps:MetroWindow>
|
||||
|
71
Wabbajack/Views/WebBrowserView.xaml
Normal file
71
Wabbajack/Views/WebBrowserView.xaml
Normal file
@ -0,0 +1,71 @@
|
||||
<UserControl x:Class="Wabbajack.WebBrowserView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
|
||||
xmlns:wabbajack="clr-namespace:Wabbajack"
|
||||
xmlns:wpf="clr-namespace:Xilium.CefGlue.WPF;assembly=Xilium.CefGlue.WPF"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<Color x:Key="TextBackgroundFill">#92000000</Color>
|
||||
<SolidColorBrush x:Key="TextBackgroundFillBrush" Color="{StaticResource TextBackgroundFill}" />
|
||||
<Color x:Key="TextBackgroundHoverFill">#DF000000</Color>
|
||||
<Style x:Key="BackgroundBlurStyle" TargetType="TextBlock">
|
||||
<Setter Property="Background" Value="{StaticResource TextBackgroundFillBrush}" />
|
||||
<Setter Property="Foreground" Value="Transparent" />
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<ColorAnimation
|
||||
Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)"
|
||||
To="{StaticResource TextBackgroundHoverFill}"
|
||||
Duration="0:0:0.06" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<ColorAnimation
|
||||
Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)"
|
||||
To="{StaticResource TextBackgroundFill}"
|
||||
Duration="0:0:0.06" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="47" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<wabbajack:TopProgressView
|
||||
Title="{Binding Instructions}"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
ShadowMargin="False" />
|
||||
<Button
|
||||
x:Name="BackButton"
|
||||
Grid.Row="0"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Margin="7,5,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
Command="{Binding BackCommand}"
|
||||
Style="{StaticResource IconCircleButtonStyle}"
|
||||
ToolTip="Back to main menu">
|
||||
<iconPacks:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" />
|
||||
</Button>
|
||||
<!-- Do it this way so we can access the browser directly from the VM -->
|
||||
<ContentControl Grid.Row="1" Content="{Binding Browser}"></ContentControl>
|
||||
</Grid>
|
||||
</UserControl>
|
28
Wabbajack/Views/WebBrowserView.xaml.cs
Normal file
28
Wabbajack/Views/WebBrowserView.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WebBrowser.xaml
|
||||
/// </summary>
|
||||
public partial class WebBrowserView : UserControl
|
||||
{
|
||||
public WebBrowserView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
@ -162,6 +162,10 @@
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="Xilium.CefGlue.WPF, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\Users\tbald\.nuget\packages\cefglue.wpf\75.1.28\lib\net472\x64\Xilium.CefGlue.WPF.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
@ -169,6 +173,7 @@
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Converters\EqualsToBoolConverter.cs" />
|
||||
<Compile Include="View Models\WebBrowserVM.cs" />
|
||||
<Compile Include="Views\Installers\MO2InstallerConfigView.xaml.cs">
|
||||
<DependentUpon>MO2InstallerConfigView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -247,6 +252,9 @@
|
||||
<Compile Include="Views\Installers\VortexInstallerConfigView.xaml.cs">
|
||||
<DependentUpon>VortexInstallerConfigView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\WebBrowserView.xaml.cs">
|
||||
<DependentUpon>WebBrowserView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="Views\Installers\MO2InstallerConfigView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@ -333,6 +341,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\WebBrowserView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
@ -411,6 +423,9 @@
|
||||
<PackageReference Include="AlphaFS">
|
||||
<Version>2.2.6</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CefGlue.Wpf">
|
||||
<Version>75.1.28</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CommonMark.NET">
|
||||
<Version>0.15.1</Version>
|
||||
</PackageReference>
|
||||
|
Loading…
Reference in New Issue
Block a user