diff --git a/Wabbajack.CLI/Assets/wabbajack.ico b/Wabbajack.CLI/Assets/wabbajack.ico new file mode 100644 index 00000000..8fa8e7b0 Binary files /dev/null and b/Wabbajack.CLI/Assets/wabbajack.ico differ diff --git a/Wabbajack.Networking.Browser.Host/App.axaml b/Wabbajack.CLI/Browser/App.axaml similarity index 50% rename from Wabbajack.Networking.Browser.Host/App.axaml rename to Wabbajack.CLI/Browser/App.axaml index e6dea0e2..cf669251 100644 --- a/Wabbajack.Networking.Browser.Host/App.axaml +++ b/Wabbajack.CLI/Browser/App.axaml @@ -1,11 +1,6 @@ - - - - + x:Class="Wabbajack.CLI.Browser.BrowserApp"> diff --git a/Wabbajack.CLI/Browser/App.axaml.cs b/Wabbajack.CLI/Browser/App.axaml.cs new file mode 100644 index 00000000..0b2d2c90 --- /dev/null +++ b/Wabbajack.CLI/Browser/App.axaml.cs @@ -0,0 +1,87 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; +using Avalonia.Threading; +using CefNet; +using Wabbajack.Paths.IO; + +namespace Wabbajack.CLI.Browser +{ + public partial class BrowserApp : Application + { + private const int messagePumpDelay = 10; + + + private static CefAppImpl app; + private static Timer messagePump; + + private CefAppImpl _cefAppImpl; + public TaskCompletionSource OnComplete { get; init; } + public IServiceProvider Provider { get; init; } + public static Window? MainWindow { get; set; } + + public static event EventHandler FrameworkInitialized; + public static event EventHandler FrameworkShutdown; + + public override void Initialize() + { + var resources = KnownFolders.EntryPoint; + var settings = new CefSettings + { + NoSandbox = true, + PersistSessionCookies = true, + MultiThreadedMessageLoop = false, + WindowlessRenderingEnabled = true, + ExternalMessagePump = true, + LocalesDirPath = resources.Combine("locales").ToString(), + ResourcesDirPath = resources.ToString(), + UserAgent = "", + CachePath = KnownFolders.WabbajackAppLocal.Combine("cef_cache").ToString() + }; + + var app = new CefAppImpl(); + app.ScheduleMessagePumpWorkCallback = OnScheduleMessagePumpWork; + + app.CefProcessMessageReceived += App_CefProcessMessageReceived; + app.Initialize(resources.ToString(), settings); + + Dispatcher.UIThread.Post(() => Thread.CurrentThread.Name = "UIThread"); + AvaloniaXamlLoader.Load(this); + } + + private static async void OnScheduleMessagePumpWork(long delayMs) + { + await Task.Delay((int) delayMs); + Dispatcher.UIThread.Post(CefApi.DoMessageLoopWork); + } + + private static void App_CefProcessMessageReceived(object? sender, CefProcessMessageReceivedEventArgs e) + { + var msg = e.Name; + } + + public override void OnFrameworkInitializationCompleted() + { + base.OnFrameworkInitializationCompleted(); + if (CefNetApplication.Instance.UsesExternalMessageLoop) + messagePump = new Timer(_ => Dispatcher.UIThread.Post(CefApi.DoMessageLoopWork), null, messagePumpDelay, + messagePumpDelay); + OnComplete.SetResult(); + + } + + private void Startup(object sender, ControlledApplicationLifetimeStartupEventArgs e) + { + FrameworkInitialized?.Invoke(this, EventArgs.Empty); + } + + private void Exit(object sender, ControlledApplicationLifetimeExitEventArgs e) + { + FrameworkShutdown?.Invoke(this, EventArgs.Empty); + } + } +} \ No newline at end of file diff --git a/Wabbajack.Networking.Browser.Host/BrowserExtensions.cs b/Wabbajack.CLI/Browser/BrowserExtensions.cs similarity index 97% rename from Wabbajack.Networking.Browser.Host/BrowserExtensions.cs rename to Wabbajack.CLI/Browser/BrowserExtensions.cs index 70064377..c2daf11f 100644 --- a/Wabbajack.Networking.Browser.Host/BrowserExtensions.cs +++ b/Wabbajack.CLI/Browser/BrowserExtensions.cs @@ -7,7 +7,7 @@ using CefNet.Avalonia; using HtmlAgilityPack; using Wabbajack.DTOs.Logins; -namespace Wabbajack.Networking.Browser; +namespace Wabbajack.CLI.Browser; public static class BrowserExtensions { diff --git a/Wabbajack.CLI/Browser/BrowserHost.cs b/Wabbajack.CLI/Browser/BrowserHost.cs new file mode 100644 index 00000000..8e8dd327 --- /dev/null +++ b/Wabbajack.CLI/Browser/BrowserHost.cs @@ -0,0 +1,70 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Avalonia; +using Avalonia.Controls; +using Avalonia.ReactiveUI; +using Avalonia.Threading; +using CefNet; +using CefNet.Avalonia; +using Microsoft.Extensions.DependencyInjection; + +namespace Wabbajack.CLI.Browser +{ + public class BrowserHost + { + private TaskCompletionSource _startupTask = new(); + private readonly IServiceProvider _serviceProvider; + + public BrowserHost(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + var th = new Thread(() => + { + BuildAvaloniaApp() + .StartWithCefNetApplicationLifetime(Array.Empty(), ShutdownMode.OnExplicitShutdown); + }); + th.SetApartmentState(ApartmentState.STA); + th.Start(); + } + + // Avalonia configuration, don't remove; also used by visual designer. + public AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure(() => new BrowserApp + { + Provider = _serviceProvider, + OnComplete = _startupTask + }) + .UsePlatformDetect() + .LogToTrace() + .UseReactiveUI(); + + public async Task CreateBrowser() + { + await _startupTask.Task; + var tcs = new TaskCompletionSource(); + await Dispatcher.UIThread.InvokeAsync(() => + { + var window = _serviceProvider.GetRequiredService(); + window.ViewModel = _serviceProvider.GetRequiredService(); + window.Show(); + tcs.SetResult(new BrowserState(window, window.ViewModel, window.Browser)); + }); + return await tcs.Task; + } + } + + public class BrowserState + { + private MainWindow _mainWindow; + private MainWindowViewModel _mainWindowViewModel; + private readonly CustomWebView _browser; + + public BrowserState(MainWindow mainWindow, MainWindowViewModel vm, CustomWebView browser) + { + _mainWindow = mainWindow; + _mainWindowViewModel = vm; + _browser = browser; + } + } +} diff --git a/Wabbajack.Networking.Browser.Host/CefAppImpl.cs b/Wabbajack.CLI/Browser/CefAppImpl.cs similarity index 96% rename from Wabbajack.Networking.Browser.Host/CefAppImpl.cs rename to Wabbajack.CLI/Browser/CefAppImpl.cs index 2888314d..34b3c596 100644 --- a/Wabbajack.Networking.Browser.Host/CefAppImpl.cs +++ b/Wabbajack.CLI/Browser/CefAppImpl.cs @@ -2,9 +2,9 @@ using System; using System.Runtime.InteropServices; using CefNet; -namespace Wabbajack.Networking.Browser; +namespace Wabbajack.CLI.Browser; -internal class CefAppImpl : CefNetApplication +public class CefAppImpl : CefNetApplication { public Action ScheduleMessagePumpWorkCallback { get; set; } diff --git a/Wabbajack.Networking.Browser.Host/CustomWebView.cs b/Wabbajack.CLI/Browser/CustomWebView.cs similarity index 87% rename from Wabbajack.Networking.Browser.Host/CustomWebView.cs rename to Wabbajack.CLI/Browser/CustomWebView.cs index a179c444..0700114d 100644 --- a/Wabbajack.Networking.Browser.Host/CustomWebView.cs +++ b/Wabbajack.CLI/Browser/CustomWebView.cs @@ -4,24 +4,20 @@ using CefNet.Avalonia; using CefNet.Internal; using Wabbajack.Paths; -namespace Wabbajack.Networking.Browser; +namespace Wabbajack.CLI.Browser; public class CustomWebView : WebView { - private CustomGlue Glue { get; } - - public CustomWebView() : base() - { - Glue = new CustomGlue(this); - } + public CustomGlue Glue { get; private set; } protected override WebViewGlue CreateWebViewGlue() { + Glue = new CustomGlue(this); return Glue; } } -class CustomGlue : AvaloniaWebViewGlue +public class CustomGlue : AvaloniaWebViewGlue { private readonly CustomWebView _view; public Func? RedirectDownloadsFn { get; set; } diff --git a/Wabbajack.Networking.Browser.Host/Views/MainWindow.axaml b/Wabbajack.CLI/Browser/MainWindow.axaml similarity index 81% rename from Wabbajack.Networking.Browser.Host/Views/MainWindow.axaml rename to Wabbajack.CLI/Browser/MainWindow.axaml index 43e00b02..0c831157 100644 --- a/Wabbajack.Networking.Browser.Host/Views/MainWindow.axaml +++ b/Wabbajack.CLI/Browser/MainWindow.axaml @@ -1,15 +1,15 @@ - - - - diff --git a/Wabbajack.Networking.Browser.Host/Views/MainWindow.axaml.cs b/Wabbajack.CLI/Browser/MainWindow.axaml.cs similarity index 88% rename from Wabbajack.Networking.Browser.Host/Views/MainWindow.axaml.cs rename to Wabbajack.CLI/Browser/MainWindow.axaml.cs index 33b1b45b..8ce45d29 100644 --- a/Wabbajack.Networking.Browser.Host/Views/MainWindow.axaml.cs +++ b/Wabbajack.CLI/Browser/MainWindow.axaml.cs @@ -3,9 +3,8 @@ using Avalonia; using Avalonia.Controls.Mixins; using Avalonia.ReactiveUI; using ReactiveUI; -using Wabbajack.Networking.Browser.ViewModels; -namespace Wabbajack.Networking.Browser.Views +namespace Wabbajack.CLI.Browser { public partial class MainWindow : ReactiveWindow diff --git a/Wabbajack.Networking.Browser.Host/ViewModels/MainWindowViewModel.cs b/Wabbajack.CLI/Browser/MainWindowViewModel.cs similarity index 82% rename from Wabbajack.Networking.Browser.Host/ViewModels/MainWindowViewModel.cs rename to Wabbajack.CLI/Browser/MainWindowViewModel.cs index 0b1d253e..8613d6d7 100644 --- a/Wabbajack.Networking.Browser.Host/ViewModels/MainWindowViewModel.cs +++ b/Wabbajack.CLI/Browser/MainWindowViewModel.cs @@ -1,6 +1,6 @@ using ReactiveUI.Fody.Helpers; -namespace Wabbajack.Networking.Browser.ViewModels +namespace Wabbajack.CLI.Browser { public class MainWindowViewModel : ViewModelBase { diff --git a/Wabbajack.Networking.Browser.Host/ViewModels/ViewModelBase.cs b/Wabbajack.CLI/Browser/ViewModelBase.cs similarity index 63% rename from Wabbajack.Networking.Browser.Host/ViewModels/ViewModelBase.cs rename to Wabbajack.CLI/Browser/ViewModelBase.cs index 07911712..ea56d2df 100644 --- a/Wabbajack.Networking.Browser.Host/ViewModels/ViewModelBase.cs +++ b/Wabbajack.CLI/Browser/ViewModelBase.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; -using ReactiveUI; +using ReactiveUI; -namespace Wabbajack.Networking.Browser.ViewModels +namespace Wabbajack.CLI.Browser { public class ViewModelBase : ReactiveObject, IActivatableViewModel { diff --git a/Wabbajack.CLI/Program.cs b/Wabbajack.CLI/Program.cs index 30b0bd08..55c80ff7 100644 --- a/Wabbajack.CLI/Program.cs +++ b/Wabbajack.CLI/Program.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Octokit; +using Wabbajack.CLI.Browser; using Wabbajack.CLI.TypeConverters; using Wabbajack.CLI.Verbs; using Wabbajack.DTOs.GitHub; @@ -25,6 +26,7 @@ namespace Wabbajack.CLI; internal class Program { + [STAThread] private static async Task Main(string[] args) { TypeDescriptor.AddAttributes(typeof(AbsolutePath), @@ -52,6 +54,10 @@ internal class Program services.AddOSIntegrated(); services.AddServerLib(); + services.AddSingleton(); + services.AddSingleton(); + + services.AddSingleton(); services.AddTransient(); @@ -62,6 +68,7 @@ internal class Program services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -88,6 +95,7 @@ internal class Program reg.Register(UploadToNexus.MakeCommand); reg.Register(ValidateLists.MakeCommand); reg.Register(VfsIndexFolder.MakeCommand); + reg.Register(NexusLogin.MakeCommand); return await service!.Run(args); } diff --git a/Wabbajack.CLI/Verbs/ManualDownload.cs b/Wabbajack.CLI/Verbs/ManualDownload.cs deleted file mode 100644 index 86047802..00000000 --- a/Wabbajack.CLI/Verbs/ManualDownload.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System; -using System.CommandLine; -using System.CommandLine.Invocation; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Wabbajack.Networking.Browser; -using Wabbajack.Paths; -using Wabbajack.RateLimiter; - -namespace Wabbajack.CLI.Verbs; - -public class ManualDownload -{ - private readonly ILogger _logger; - private readonly Client _client; - private readonly IResource _limiter; - - public ManualDownload(ILogger logger, Client client, IResource limiter) - { - _logger = logger; - _client = client; - _limiter = limiter; - } - public Command MakeCommand() - { - var command = new Command("manual-download"); - command.Add(new Option(new[] {"-p", "-prompt"}, "Text prompt to show the user")); - command.Add(new Option(new[] {"-u", "-url"}, "Uri to show the user")); - command.Add(new Option(new[] {"-o", "-outputPath"}, "Output Path for the downloaded file")); - command.Description = "Shows a browser and instructs the user to download a file, exist when the file is downloaded"; - command.Handler = CommandHandler.Create(Run); - return command; - } - - public async Task Run(string prompt, Uri url, AbsolutePath outputPath, CancellationToken token) - { - _logger.LogInformation("Opening browser"); - using var job = await _limiter.Begin($"Downloading {url}", 0, token); - await _client.ManualDownload(prompt, url, outputPath, token, job); - return 0; - } -} \ No newline at end of file diff --git a/Wabbajack.CLI/Verbs/NexusLogin.cs b/Wabbajack.CLI/Verbs/NexusLogin.cs new file mode 100644 index 00000000..30771b3f --- /dev/null +++ b/Wabbajack.CLI/Verbs/NexusLogin.cs @@ -0,0 +1,39 @@ +using System.CommandLine; +using System.CommandLine.Invocation; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Wabbajack.CLI.Browser; + +namespace Wabbajack.CLI.Verbs; + +public class NexusLogin : AVerb +{ + private readonly ILogger _logger; + private readonly BrowserHost _host; + + public NexusLogin(ILogger logger, BrowserHost host) + { + _logger = logger; + _host = host; + } + + public static Command MakeCommand() + { + var command = new Command("nexus-login"); + command.Description = "Prompt the user to log into the nexus"; + return command; + } + + public async Task Run(CancellationToken token) + { + var browser = await _host.CreateBrowser(); + + return 0; + } + + protected override ICommandHandler GetHandler() + { + return CommandHandler.Create(Run); + } +} \ No newline at end of file diff --git a/Wabbajack.CLI/Wabbajack.CLI.csproj b/Wabbajack.CLI/Wabbajack.CLI.csproj index 38262240..d97ce8f3 100644 --- a/Wabbajack.CLI/Wabbajack.CLI.csproj +++ b/Wabbajack.CLI/Wabbajack.CLI.csproj @@ -10,6 +10,7 @@ wabbajack-cli true linked + true @@ -19,6 +20,7 @@ + @@ -33,4 +35,20 @@ + + + App.axaml + Code + + + MainWindow.axaml + Code + + + + + + + + diff --git a/Wabbajack.Networking.Browser.Host/.gitignore b/Wabbajack.Networking.Browser.Host/.gitignore deleted file mode 100644 index 8afdcb63..00000000 --- a/Wabbajack.Networking.Browser.Host/.gitignore +++ /dev/null @@ -1,454 +0,0 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# Tye -.tye/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -## -## Visual studio for Mac -## - - -# globs -Makefile.in -*.userprefs -*.usertasks -config.make -config.status -aclocal.m4 -install-sh -autom4te.cache/ -*.tar.gz -tarballs/ -test-results/ - -# Mac bundle stuff -*.dmg -*.app - -# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore -# Windows thumbnail cache files -Thumbs.db -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# JetBrains Rider -.idea/ -*.sln.iml - -## -## Visual Studio Code -## -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json diff --git a/Wabbajack.Networking.Browser.Host/App.axaml.cs b/Wabbajack.Networking.Browser.Host/App.axaml.cs deleted file mode 100644 index 1d094ded..00000000 --- a/Wabbajack.Networking.Browser.Host/App.axaml.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Markup.Xaml; -using Avalonia.Threading; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using ReactiveUI; -using Splat; -using Wabbajack.DTOs.BrowserMessages; -using Wabbajack.DTOs.JsonConverters; -using Wabbajack.Networking.Browser.ViewModels; -using Wabbajack.Networking.Browser.Views; - -namespace Wabbajack.Networking.Browser -{ - public class App : Application - { - public static IServiceProvider Services { get; private set; } = null!; - public static Window? MainWindow { get; set; } - - public static event EventHandler FrameworkInitialized; - public static event EventHandler FrameworkShutdown; - - public override void Initialize() - { - Dispatcher.UIThread.Post(() => Thread.CurrentThread.Name = "UIThread"); - AvaloniaXamlLoader.Load(this); - } - - public override void OnFrameworkInitializationCompleted() - { - var host = Host.CreateDefaultBuilder(Array.Empty()) - .ConfigureLogging(c => { c.ClearProviders(); }) - .ConfigureServices((host, services) => { services.AddAppServices(); }).Build(); - Services = host.Services; - - - // Need to startup the message bus; - var app = Services.GetService(); - - if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - Program.MainWindow = Services.GetRequiredService(); - Program.MainWindowVM = Services.GetRequiredService(); - Program.MainWindow.ViewModel = Program.MainWindowVM; - desktop.MainWindow = Program.MainWindow; - desktop.Startup += Startup; - desktop.Exit += Exit; - MainWindow = desktop.MainWindow; - } - - base.OnFrameworkInitializationCompleted(); - - - var dtos = Services.GetRequiredService(); - var msgProcessor = Task.Run(async () => - { - await using var input = Console.OpenStandardInput(); - while (true) - { - var msg = await JsonSerializer.DeserializeAsync(input); - switch (msg) - { - - } - } - - }); - } - - private void Startup(object sender, ControlledApplicationLifetimeStartupEventArgs e) - { - FrameworkInitialized?.Invoke(this, EventArgs.Empty); - } - - private void Exit(object sender, ControlledApplicationLifetimeExitEventArgs e) - { - FrameworkShutdown?.Invoke(this, EventArgs.Empty); - } - } -} \ No newline at end of file diff --git a/Wabbajack.Networking.Browser.Host/Assets/avalonia-logo.ico b/Wabbajack.Networking.Browser.Host/Assets/avalonia-logo.ico deleted file mode 100644 index da8d49ff..00000000 Binary files a/Wabbajack.Networking.Browser.Host/Assets/avalonia-logo.ico and /dev/null differ diff --git a/Wabbajack.Networking.Browser.Host/FodyWeavers.xml b/Wabbajack.Networking.Browser.Host/FodyWeavers.xml deleted file mode 100644 index 63fc1484..00000000 --- a/Wabbajack.Networking.Browser.Host/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/Wabbajack.Networking.Browser.Host/Program.cs b/Wabbajack.Networking.Browser.Host/Program.cs deleted file mode 100644 index 123e9b30..00000000 --- a/Wabbajack.Networking.Browser.Host/Program.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using Avalonia; -using Avalonia.ReactiveUI; -using CefNet; -using Wabbajack.Networking.Browser.ViewModels; -using Wabbajack.Networking.Browser.Views; - -namespace Wabbajack.Networking.Browser -{ - class Program - { - public static MainWindowViewModel MainWindowVM { get; set; } - public static string[] Args { get; set; } - - public static Views.MainWindow MainWindow { get; set; } - - // Initialization code. Don't use any Avalonia, third-party APIs or any - // SynchronizationContext-reliant code before AppMain is called: things aren't initialized - // yet and stuff might break. - [STAThread] - public static void Main(string[] args) - { - Args = args; - BuildAvaloniaApp() - .StartWithCefNetApplicationLifetime(args); - - - } - - // Avalonia configuration, don't remove; also used by visual designer. - public static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure() - .UsePlatformDetect() - .LogToTrace() - .UseReactiveUI(); - } -} diff --git a/Wabbajack.Networking.Browser.Host/ServiceExtensions.cs b/Wabbajack.Networking.Browser.Host/ServiceExtensions.cs deleted file mode 100644 index fb8cb4be..00000000 --- a/Wabbajack.Networking.Browser.Host/ServiceExtensions.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.ComponentModel; -using System.Threading; -using System.Threading.Tasks; -using Avalonia.Threading; -using CefNet; -using Microsoft.Extensions.DependencyInjection; -using Wabbajack.CLI.TypeConverters; -using Wabbajack.Networking.Browser.ViewModels; -using Wabbajack.Networking.Browser.Views; -using Wabbajack.Paths; -using Wabbajack.Paths.IO; -using Wabbajack.Services.OSIntegrated; - -namespace Wabbajack.Networking.Browser; - -public static class ServiceExtensions -{ - private const int messagePumpDelay = 10; - - - private static CefAppImpl app; - private static Timer messagePump; - - public static IServiceCollection AddAppServices(this IServiceCollection services) - { - - TypeDescriptor.AddAttributes(typeof(AbsolutePath), - new TypeConverterAttribute(typeof(AbsolutePathTypeConverter))); - - var resources = KnownFolders.EntryPoint; - services.AddSingleton(); - services.AddSingleton(); - - services.AddOSIntegrated(); - - services.AddSingleton(s => new CefSettings - { - NoSandbox = true, - PersistSessionCookies = true, - MultiThreadedMessageLoop = false, - WindowlessRenderingEnabled = true, - ExternalMessagePump = true, - LocalesDirPath = resources.Combine("locales").ToString(), - ResourcesDirPath = resources.ToString(), - UserAgent = "", - CachePath = KnownFolders.WabbajackAppLocal.Combine("cef_cache").ToString() - }); - - services.AddSingleton(s => - { - App.FrameworkInitialized += App_FrameworkInitialized; - - var app = new CefAppImpl(); - app.ScheduleMessagePumpWorkCallback = OnScheduleMessagePumpWork; - - app.CefProcessMessageReceived += App_CefProcessMessageReceived; - app.Initialize(resources.ToString(), s.GetService()); - - - return app; - }); - - return services; - } - - private static async void OnScheduleMessagePumpWork(long delayMs) - { - await Task.Delay((int) delayMs); - Dispatcher.UIThread.Post(CefApi.DoMessageLoopWork); - } - - private static void App_CefProcessMessageReceived(object? sender, CefProcessMessageReceivedEventArgs e) - { - var msg = e.Name; - } - - private static void App_FrameworkInitialized(object? sender, EventArgs e) - { - if (CefNetApplication.Instance.UsesExternalMessageLoop) - messagePump = new Timer(_ => Dispatcher.UIThread.Post(CefApi.DoMessageLoopWork), null, messagePumpDelay, - messagePumpDelay); - } -} \ No newline at end of file diff --git a/Wabbajack.Networking.Browser.Host/TypeConverters/AbsolutePathTypeConverter.cs b/Wabbajack.Networking.Browser.Host/TypeConverters/AbsolutePathTypeConverter.cs deleted file mode 100644 index 39725cd0..00000000 --- a/Wabbajack.Networking.Browser.Host/TypeConverters/AbsolutePathTypeConverter.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.ComponentModel; -using System.Globalization; -using Wabbajack.Paths; - -namespace Wabbajack.CLI.TypeConverters; - -public class AbsolutePathTypeConverter : TypeConverter -{ - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, - Type destinationType) - { - return (AbsolutePath) (string) value; - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - return (AbsolutePath) (string) value; - } -} \ No newline at end of file diff --git a/Wabbajack.Networking.Browser.Host/TypeConverters/ModListCategoryConverter.cs b/Wabbajack.Networking.Browser.Host/TypeConverters/ModListCategoryConverter.cs deleted file mode 100644 index e413e3fe..00000000 --- a/Wabbajack.Networking.Browser.Host/TypeConverters/ModListCategoryConverter.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.ComponentModel; -using System.Globalization; -using Wabbajack.DTOs.GitHub; - -namespace Wabbajack.Networking.Browser.TypeConverters; - -public class ModListCategoryConverter : TypeConverter -{ - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, - Type destinationType) - { - throw new NotImplementedException(); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - return Enum.Parse((string) value); - } -} \ No newline at end of file diff --git a/Wabbajack.Networking.Browser.Host/ViewLocator.cs b/Wabbajack.Networking.Browser.Host/ViewLocator.cs deleted file mode 100644 index c11ec087..00000000 --- a/Wabbajack.Networking.Browser.Host/ViewLocator.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Avalonia.Controls; -using Avalonia.Controls.Templates; -using Wabbajack.Networking.Browser.ViewModels; - -namespace Wabbajack.Networking.Browser -{ - public class ViewLocator : IDataTemplate - { - public IControl Build(object data) - { - var name = data.GetType().FullName!.Replace("ViewModel", "View"); - var type = Type.GetType(name); - - if (type != null) - { - return (Control)Activator.CreateInstance(type)!; - } - else - { - return new TextBlock { Text = "Not Found: " + name }; - } - } - - public bool Match(object data) - { - return data is ViewModelBase; - } - } -} \ No newline at end of file diff --git a/Wabbajack.Networking.Browser.Host/Wabbajack.Networking.Browser.Host.csproj b/Wabbajack.Networking.Browser.Host/Wabbajack.Networking.Browser.Host.csproj deleted file mode 100644 index 58946b26..00000000 --- a/Wabbajack.Networking.Browser.Host/Wabbajack.Networking.Browser.Host.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - Exe - net6.0 - enable - 10 - Wabbajack.Networking.Browser - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Wabbajack.Networking.Browser/Client.cs b/Wabbajack.Networking.Browser/Client.cs deleted file mode 100644 index 7b1215b0..00000000 --- a/Wabbajack.Networking.Browser/Client.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Diagnostics; -using System.Text.Json; -using Wabbajack.DTOs.BrowserMessages; -using Wabbajack.DTOs.JsonConverters; -using Wabbajack.Paths; -using Wabbajack.RateLimiter; - -namespace Wabbajack.Networking.Browser; - - -public class Client -{ - private readonly Configuration _config; - private readonly DTOSerializer _dtos; - - public Client(Configuration config, DTOSerializer dtos) - { - _config = config; - _dtos = dtos; - } - - public async Task ManualDownload(string prompt, Uri uri, AbsolutePath dest, CancellationToken token, IJob job) - { - var process = new Process() - { - StartInfo = new ProcessStartInfo() - { - FileName = _config.HostExecutable.ToString(), - RedirectStandardError = true, - RedirectStandardInput = true, - RedirectStandardOutput = true - } - }; - - var ptask = process.Start(); - - var reader = Task.Run(async () => - { - while (!token.IsCancellationRequested) - { - var msg = await JsonSerializer.DeserializeAsync(process.StandardOutput.BaseStream, - _dtos.Options, token); - if (msg is DownloadProgress dp) - { - job.ReportNoWait((int) dp.BytesCompleted); - job.Size = dp.ExpectedSize; - if (dp.IsDone) - { - return; - } - } - } - }, token); - - await process.StandardInput.WriteAsync(JsonSerializer.Serialize(new DTOs.BrowserMessages.ManualDownload() - { - Prompt = prompt, - Url = uri, - Path = dest - })); - - await process.WaitForExitAsync(token); - - } -} \ No newline at end of file diff --git a/Wabbajack.Networking.Browser/Configuration.cs b/Wabbajack.Networking.Browser/Configuration.cs deleted file mode 100644 index 8f537b51..00000000 --- a/Wabbajack.Networking.Browser/Configuration.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Wabbajack.Paths; -using Wabbajack.Paths.IO; - -namespace Wabbajack.Networking.Browser; - -public class Configuration -{ - public AbsolutePath HostExecutable { get; set; } = - KnownFolders.EntryPoint.Combine("Wabbajack.Networking.Browser.Host.exe"); -} \ No newline at end of file diff --git a/Wabbajack.Networking.Browser/Wabbajack.Networking.Browser.csproj b/Wabbajack.Networking.Browser/Wabbajack.Networking.Browser.csproj deleted file mode 100644 index c1f0a5f7..00000000 --- a/Wabbajack.Networking.Browser/Wabbajack.Networking.Browser.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - net6.0 - enable - enable - Wabbajack.Networking.Browser.Client - - - - - - - - - - diff --git a/Wabbajack.sln b/Wabbajack.sln index c1fd6ae4..f0008b0d 100644 --- a/Wabbajack.sln +++ b/Wabbajack.sln @@ -125,10 +125,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wabbajack.App.Blazor", "Wab EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{18E36813-CB53-4172-8FF3-EFE3B9B30A5F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Networking.Browser.Host", "Wabbajack.Networking.Browser.Host\Wabbajack.Networking.Browser.Host.csproj", "{44860A8E-C3E4-4BF0-8EAB-BFA2D6DA217A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Networking.Browser", "Wabbajack.Networking.Browser\Wabbajack.Networking.Browser.csproj", "{860A06B3-AE35-4C69-95E5-EC9E8D6630CF}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -343,14 +339,6 @@ Global {C6E9B15D-510F-4074-AB1C-069F36BA4622}.Debug|Any CPU.Build.0 = Debug|Any CPU {C6E9B15D-510F-4074-AB1C-069F36BA4622}.Release|Any CPU.ActiveCfg = Release|Any CPU {C6E9B15D-510F-4074-AB1C-069F36BA4622}.Release|Any CPU.Build.0 = Release|Any CPU - {44860A8E-C3E4-4BF0-8EAB-BFA2D6DA217A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {44860A8E-C3E4-4BF0-8EAB-BFA2D6DA217A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {44860A8E-C3E4-4BF0-8EAB-BFA2D6DA217A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {44860A8E-C3E4-4BF0-8EAB-BFA2D6DA217A}.Release|Any CPU.Build.0 = Release|Any CPU - {860A06B3-AE35-4C69-95E5-EC9E8D6630CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {860A06B3-AE35-4C69-95E5-EC9E8D6630CF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {860A06B3-AE35-4C69-95E5-EC9E8D6630CF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {860A06B3-AE35-4C69-95E5-EC9E8D6630CF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -392,8 +380,6 @@ Global {4F252332-CA77-41DE-95A8-9DF38A81D675} = {98B731EE-4FC0-4482-A069-BCBA25497871} {AB9A5C22-10CC-4EE0-A808-FB1DC9E24247} = {F01F8595-5FD7-4506-8469-F4A5522DACC1} {D6351587-CAF6-4CB6-A2BD-5368E69F297C} = {F01F8595-5FD7-4506-8469-F4A5522DACC1} - {44860A8E-C3E4-4BF0-8EAB-BFA2D6DA217A} = {F01F8595-5FD7-4506-8469-F4A5522DACC1} - {860A06B3-AE35-4C69-95E5-EC9E8D6630CF} = {F01F8595-5FD7-4506-8469-F4A5522DACC1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0AA30275-0F38-4A7D-B645-F5505178DDE8}