This commit is contained in:
erri120 2022-01-28 12:58:28 +01:00
parent 2fab1b462f
commit c4c80b7fe0
No known key found for this signature in database
GPG Key ID: 7FA9556C936B847C
19 changed files with 113 additions and 98 deletions

View File

@ -4,11 +4,5 @@ indent_style = space
indent_size = 4
insert_final_newline = true
# C# and Razor files
[*.{cs,razor}]
# RZ10012: Markup element with unexpected name.
# Reason: The component namespace is added to the global _Imports.razor file.
dotnet_diagnostic.RZ10012.severity = none
[*.scss]
indent_size = 2

View File

@ -16,15 +16,15 @@
@code {
[Parameter]
public string Title { get; set; }
public string? Title { get; set; }
[Parameter]
public string Subtitle { get; set; }
public string? Subtitle { get; set; }
[Parameter]
public string Image { get; set; }
public string? Image { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
public RenderFragment? ChildContent { get; set; }
}

View File

@ -1,7 +1,7 @@
@namespace Wabbajack.App.Blazor.Components
<div id="info-block">
@if (Supertitle != string.Empty)
@if (Supertitle is not null)
{
<span class="supertitle">@Supertitle</span>
}
@ -14,18 +14,18 @@
@code {
[Parameter]
public string Supertitle { get; set; } = string.Empty;
public string? Supertitle { get; set; }
[Parameter]
public string Title { get; set; }
public string? Title { get; set; }
[Parameter]
public string Subtitle { get; set; }
public string? Subtitle { get; set; }
[Parameter]
public string Comment { get; set; }
public string? Comment { get; set; }
[Parameter]
public string Description { get; set; }
public string? Description { get; set; }
}

View File

@ -23,15 +23,14 @@
@code {
[Parameter]
public string Image { get; set; }
public string? Image { get; set; }
[Parameter]
public string Title { get; set; }
public string? Title { get; set; }
[Parameter]
public string Subtitle { get; set; }
public string? Subtitle { get; set; }
[Parameter]
public string Description { get; set; }
public string? Description { get; set; }
}

View File

@ -5,5 +5,5 @@
@code {
[Parameter]
public string Content { get; set; }
public string? Content { get; set; }
}

View File

@ -5,15 +5,14 @@
@code {
[Parameter]
public string Icon { get; set; }
public string? Icon { get; set; }
[Parameter]
public string Label { get; set; }
public string? Label { get; set; }
[Parameter]
public string Size { get; set; }
public string? Size { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClick { get; set; }
}

View File

@ -2,26 +2,28 @@
<label class="option">
@Label
<input type="checkbox" checked="@IsChecked" @onchange="CheckBoxChanged">
<input type="checkbox" value="@IsChecked" @onchange="CheckBoxChanged">
<span class="checkmark"></span>
</label>
@code {
// TODO: [Low] Implement parameters to customize style.
// TODO: [High] Implement a way to set a passed bool without using callback function.
[Parameter]
public string Label { get; set; }
public string? Label { get; set; }
[Parameter]
public EventCallback<bool> OnChecked { get; set; }
private bool IsChecked { get; set; }
public bool IsChecked { get; set; }
[Parameter]
public EventCallback<bool> IsCheckedChanged { get; set; }
private async Task CheckBoxChanged(ChangeEventArgs e)
{
IsChecked = (bool)(e.Value ?? false);
await OnChecked.InvokeAsync(IsChecked);
if (e.Value is not bool newValue) return;
if (IsChecked == newValue) return;
IsChecked = newValue;
await IsCheckedChanged.InvokeAsync(IsChecked);
}
}

View File

@ -1,32 +1,38 @@
@using Wabbajack.RateLimiter
@using System
@using System.Reactive.Linq
@implements IDisposable
@namespace Wabbajack.App.Blazor.Components
<div id="progress-bar">
<progress value="@CurrentProgress"></progress>
<progress max="1" value="@CurrentProgress.ToString("F")"></progress>
<span class="text">@Text</span>
</div>
@code {
[Parameter] public IObservable<Percent>? ProgressObserver { get; set; }
private double CurrentProgress { get; set; }
private string Text { get; set; } = string.Empty;
[Parameter] public IObservable<Percent> ProgressObserver { get; set; }
[Parameter] public string? Text { get; set; }
private IDisposable? _disposable;
protected override void OnInitialized()
{
var textPercentage = string.IsNullOrEmpty(Text);
ProgressObserver
if (ProgressObserver is null) return;
_disposable = ProgressObserver
.Sample(TimeSpan.FromMilliseconds(250))
.DistinctUntilChanged(p => p.Value)
.Subscribe(p => {
.Subscribe(p =>
{
CurrentProgress = p.Value;
if (textPercentage) Text = p.ToString();
Text = p.ToString();
InvokeAsync(StateHasChanged);
});
}
public void Dispose() => _disposable?.Dispose();
}

View File

@ -1,4 +1,5 @@
@code {
@using Wabbajack.App.Blazor.Utility
@code {
private void OpenPatreonPage() => UIUtils.OpenWebsite(new Uri("https://www.patreon.com/user?u=11907933"));
private void OpenGithubPage() => UIUtils.OpenWebsite(new Uri("https://github.com/wabbajack-tools/wabbajack"));
private void OpenDiscord() => UIUtils.OpenWebsite(new Uri("https://discord.gg/wabbajack"));

View File

@ -3,12 +3,12 @@
@using Wabbajack.App.Blazor.Utility
@using System.Reactive.Linq
@namespace Wabbajack.App.Blazor.Components
@implements IDisposable
<div id="virtual-logger">
@foreach (var logItem in _logs)
{
<span>@logItem</span>
}
<Virtualize Items="_logs" Context="logItem" OverscanCount="5" ItemSize="24">
<span style="height: 24px">@logItem</span>
</Virtualize>
</div>
@code {
@ -16,17 +16,26 @@
// TODO: [High] Find a way to auto-scroll. (JS interop?)
private UiLoggerTarget? _loggerTarget;
private ICollection<string> _logs = Array.Empty<string>();
private ICollection<string> _logs = new List<string>();
protected override void OnInitialized()
private bool _shouldRender = false;
protected override bool ShouldRender() => _shouldRender;
private IDisposable? _disposable;
protected override Task OnInitializedAsync()
{
_loggerTarget = LogManager.Configuration.FindTargetByName<UiLoggerTarget>("ui");
// TODO: can do different things here, buffering is just the simples operation
_loggerTarget.Logs.Buffer(TimeSpan.FromSeconds(1)).Subscribe(next =>
_disposable = _loggerTarget.Logs.Sample(TimeSpan.FromMilliseconds(250)).Subscribe(next =>
{
_logs = next;
_logs.Add(next);
InvokeAsync(StateHasChanged);
});
_shouldRender = true;
return Task.CompletedTask;
}
public void Dispose() => _disposable?.Dispose();
}

View File

@ -1,6 +1,5 @@
<Fluxor.Blazor.Web.StoreInitializer/>
@using Wabbajack.App.Blazor.Shared
@using Wabbajack.App.Blazor.Shared
<CascadingBlazoredModal>
<Router AppAssembly="@GetType().Assembly">
<Found Context="routeData">

View File

@ -22,9 +22,9 @@ public partial class Gallery
[Inject] private IStateContainer StateContainer { get; set; } = default!;
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
[Inject] private ModListDownloadMaintainer Maintainer { get; set; } = default!;
[Inject] private IModalService Modal { get; set; } = default!;
private IObservable<Percent> DownloadProgress { get; set; }
private IObservable<Percent>? DownloadProgress { get; set; }
private ModlistMetadata? DownloadingMetaData { get; set; }
private IEnumerable<ModlistMetadata> Modlists => StateContainer.Modlists;
@ -58,7 +58,7 @@ public partial class Gallery
NavigationManager.NavigateTo(Configure.Route);
}
private async Task OnClickInformation(ModlistMetadata metadata)
private void OnClickInformation(ModlistMetadata metadata)
{
// TODO: [High] Implement information modal.
var parameters = new ModalParameters();

View File

@ -38,8 +38,8 @@
</div>
</div>
<div class="options">
<OptionCheckbox Label="Overwrite Installation"/>
<OptionCheckbox Label="NTFS Compression"/>
<OptionCheckbox Label="Overwrite Installation" @bind-IsChecked="OverwriteInstallation"/>
<OptionCheckbox Label="NTFS Compression" @bind-IsChecked="UseCompression"/>
<OptionCheckbox Label="Do a sweet trick"/>
<OptionCheckbox Label="Something else"/>
</div>

View File

@ -24,18 +24,19 @@ public partial class Configure
[Inject] private SettingsManager SettingsManager { get; set; } = default!;
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
[Inject] private IJSRuntime JSRuntime { get; set; } = default!;
[Inject] private IToastService toastService { get; set; }
[Inject] private IToastService ToastService { get; set; } = default!;
private ModList? Modlist => StateContainer.Modlist;
private string? ModlistImage => StateContainer.ModlistImage;
private AbsolutePath ModlistPath => StateContainer.ModlistPath;
private AbsolutePath InstallPath => StateContainer.InstallPath;
private AbsolutePath DownloadPath => StateContainer.DownloadPath;
private InstallState InstallState => StateContainer.InstallState;
private const string InstallSettingsPrefix = "install-settings-";
private bool OverwriteInstallation { get; set; }
private bool UseCompression { get; set; }
private bool _shouldRender;
protected override bool ShouldRender() => _shouldRender;
@ -55,8 +56,8 @@ public partial class Configure
}
catch (Exception e)
{
toastService.ShowError("Could not load modlist!");
Logger.LogError(e, "Exception loading Modlist file {Name}", ModlistPath);
ToastService.ShowError("Could not load modlist!");
Logger.LogError(e, "Exception loading Modlist file {Name}", ModlistPath.ToString());
NavigationManager.NavigateTo(Select.Route);
return;
}
@ -74,19 +75,19 @@ public partial class Configure
}
catch (Exception e)
{
Logger.LogWarning(e, "Exception loading previous settings for {Name}", ModlistPath);
Logger.LogWarning(e, "Exception loading previous settings for {Name}", ModlistPath.ToString());
}
try
{
var imageStream = await StandardInstaller.ModListImageStream(ModlistPath);
var dotnetImageStream = new DotNetStreamReference(imageStream);
StateContainer.ModlistImage = await JSRuntime.InvokeAsync<string>("getBlobUrlFromStream", dotnetImageStream);
StateContainer.ModlistImage = await JSRuntime.InvokeAsync<string>(JsInterop.GetBlobUrlFromStream, dotnetImageStream);
}
catch (Exception e)
{
toastService.ShowWarning("Could not load modlist image.");
Logger.LogWarning(e, "Exception loading modlist image for {Name}", ModlistPath);
ToastService.ShowWarning("Could not load modlist image.");
Logger.LogWarning(e, "Exception loading modlist image for {Name}", ModlistPath.ToString());
}
}

View File

@ -4,7 +4,10 @@
<div id="content">
<div class="install-background">
<img id="background-image" src="@ModlistImage" alt=""/>
@if (ModlistImage is not null)
{
<img id="background-image" src="@ModlistImage" alt=""/>
}
</div>
<div class="list">
@if (Modlist is not null)

View File

@ -29,36 +29,31 @@ public partial class Installing
[Inject] private IJSRuntime JSRuntime { get; set; } = default!;
private ModList? Modlist => StateContainer.Modlist;
private string ModlistImage => StateContainer.ModlistImage;
private string? ModlistImage => StateContainer.ModlistImage;
private AbsolutePath ModlistPath => StateContainer.ModlistPath;
private AbsolutePath InstallPath => StateContainer.InstallPath;
private AbsolutePath DownloadPath => StateContainer.DownloadPath;
public string StatusCategory { get; set; }
private string LastStatus { get; set; }
public List<string> StatusStep { get; set; } = new();
private InstallState InstallState => StateContainer.InstallState;
private string? StatusCategory { get; set; }
private string? LastStatus { get; set; }
private List<string> StatusStep { get; set; } = new();
private const string InstallSettingsPrefix = "install-settings-";
private bool _shouldRender;
protected override bool ShouldRender() => _shouldRender;
protected override void OnInitialized()
protected override async Task OnInitializedAsync()
{
Install();
_shouldRender = true;
await Task.Run(Install);
}
private async Task Install()
{
if (Modlist is null) return;
StateContainer.InstallState = InstallState.Installing;
await Task.Run(() => BeginInstall(Modlist));
await BeginInstall(Modlist);
}
private async Task BeginInstall(ModList modlist)

View File

@ -2,6 +2,7 @@
@inherits LayoutComponentBase
@namespace Wabbajack.App.Blazor.Shared
<BlazoredToasts Position="ToastPosition.BottomRight"/>
<div id="background"></div>
<SideBar/>

View File

@ -0,0 +1,12 @@
using Microsoft.JSInterop;
namespace Wabbajack.App.Blazor.Utility;
public static class JsInterop
{
/// <summary>
/// Converts a <see cref="DotNetStreamReference"/> into a blob URL. Useful for streaming images.
/// <code>async function getBlobUrlFromStream(imageStream: DotNetStreamReference)</code>
/// </summary>
public const string GetBlobUrlFromStream = "getBlobUrlFromStream";
}

View File

@ -1,16 +1,10 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media.Imaging;
using Wabbajack.Hashing.xxHash64;
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
namespace Wabbajack
namespace Wabbajack.App.Blazor.Utility
{
public static class UIUtils
{
@ -31,11 +25,11 @@ namespace Wabbajack
}
public static AbsolutePath OpenFileDialog(string filter, string initialDirectory = null)
public static AbsolutePath OpenFileDialog(string filter, string? initialDirectory = null)
{
OpenFileDialog ofd = new OpenFileDialog();
var ofd = new OpenFileDialog();
ofd.Filter = filter;
ofd.InitialDirectory = initialDirectory;
ofd.InitialDirectory = initialDirectory ?? string.Empty;
if (ofd.ShowDialog() == DialogResult.OK)
return (AbsolutePath)ofd.FileName;
return default;