From 1571455393f327625dc756f52dd8ae8899ee5dab Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Tue, 22 Aug 2023 17:10:13 +0200 Subject: [PATCH] More loading states and UI updates --- BTCPayApp.UI/Constants.cs | 8 +- BTCPayApp.UI/Features/RootState.cs | 3 +- BTCPayApp.UI/Pages/WalletSetupPage.razor | 2 + .../BTCPayServerOnchainWalletConfigure.razor | 54 +++++--- .../Configuration/PairBTCPayServer.razor | 14 +- BTCPayApp.UI/Shared/Dashboard.razor | 125 +++++++++++------- BTCPayApp.UI/Shared/Onboarding.razor | 42 +----- BTCPayApp.UI/StateMiddleware.cs | 6 + 8 files changed, 132 insertions(+), 122 deletions(-) diff --git a/BTCPayApp.UI/Constants.cs b/BTCPayApp.UI/Constants.cs index 03548b1..33f9464 100644 --- a/BTCPayApp.UI/Constants.cs +++ b/BTCPayApp.UI/Constants.cs @@ -114,8 +114,8 @@ public static class Brand PrimaryContrastText = Colors.White, Secondary = Colors.White, SecondaryContrastText = Colors.Primary500, - Tertiary = Colors.White, - TertiaryContrastText = Colors.Light500, + Tertiary = Colors.Light500, + TertiaryContrastText = Colors.White, Info = Colors.Blue500, InfoContrastText = Colors.White, Success = Colors.Green500, @@ -156,8 +156,8 @@ public static class Brand PrimaryContrastText = Colors.White, Secondary = Colors.White, SecondaryContrastText = Colors.Primary500, - Tertiary = Colors.White, - TertiaryContrastText = Colors.Dark500, + Tertiary = Colors.Dark500, + TertiaryContrastText = Colors.Black, Info = Colors.Blue500, InfoContrastText = Colors.White, Success = Colors.Green500, diff --git a/BTCPayApp.UI/Features/RootState.cs b/BTCPayApp.UI/Features/RootState.cs index ef3a5e8..0e1114f 100644 --- a/BTCPayApp.UI/Features/RootState.cs +++ b/BTCPayApp.UI/Features/RootState.cs @@ -19,7 +19,8 @@ public enum LoadingHandles UiState, PairConfig, WalletConfig, - TransactionState + TransactionState, + LightningState } public RootState() : this(new HashSet(), null, null, null, LightningNodeState.NotConfigured, false, false) diff --git a/BTCPayApp.UI/Pages/WalletSetupPage.razor b/BTCPayApp.UI/Pages/WalletSetupPage.razor index 2209de8..8410ae1 100644 --- a/BTCPayApp.UI/Pages/WalletSetupPage.razor +++ b/BTCPayApp.UI/Pages/WalletSetupPage.razor @@ -29,12 +29,14 @@ var xpub = mKey.Derive(kp).Neuter().ToString(Network.Main); if (obj is { UseExisting: false, SetStore: true }) { + Dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.WalletConfig, true)); await BTCPayConnection.Client.UpdateStoreOnChainPaymentMethod(config.PairingResult.StoreId, "BTC", new UpdateOnChainPaymentMethodRequest { Enabled = true, DerivationScheme = xpub, AccountKeyPath = new RootedKeyPath(mKey, kp) }); + Dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.WalletConfig, false)); } Dispatcher.Dispatch(new RootState.WalletConfigLoadedAction(new WalletConfig { diff --git a/BTCPayApp.UI/Shared/Configuration/BTCPayServerOnchainWalletConfigure.razor b/BTCPayApp.UI/Shared/Configuration/BTCPayServerOnchainWalletConfigure.razor index a3d74a2..444bd09 100644 --- a/BTCPayApp.UI/Shared/Configuration/BTCPayServerOnchainWalletConfigure.razor +++ b/BTCPayApp.UI/Shared/Configuration/BTCPayServerOnchainWalletConfigure.razor @@ -7,21 +7,33 @@ @if (ConfiguredWallet is not null) { - @if (IsConfiguredWalletHot) - { - Your BTCPay Server store already has an onchain hot wallet configured. Would you like to: - } - else - { - Your BTCPay Server store already has an onchain watch-only wallet configured. Would you like to: - } + + @if (IsConfiguredWalletHot) + { + Your BTCPay Server store already has an onchain hot wallet configured. + } + else + { + Your BTCPay Server store already has an onchain watch-only wallet configured. + } + } - + @foreach (var option in Options) { - @option.Value +
+ +
+ @option.Value.Item1 + @if (option.Value.Item2) + { + Your existing wallet will be overwritten! + } +
+
+
}
@if (IsMnemonicRequired) @@ -29,13 +41,15 @@ } - Continue + + Continue +
@code { @@ -50,25 +64,25 @@ get { return new[] {"use-configured-wallet", "create-wallet", "create-wallet-separate"}.Contains(SelectedOption); } } - private Dictionary Options + private Dictionary Options { get { - var result = new Dictionary(); - var warningPrefix = ""; + var result = new Dictionary(); + var hasWarning = false; if (ConfiguredWallet is not null) { if (IsConfiguredWalletHot) { - result.Add("use-configured-hot-wallet", "Import the configured hot wallet"); + result.Add("use-configured-hot-wallet", ("Import the configured hot wallet", false)); } - result.Add("use-configured-wallet", "Import the configured wallet but store the keys on app"); - warningPrefix = "⚠️ Your BTCPay Server store wallet will be overwritten! ⚠️ "; + result.Add("use-configured-wallet", ("Import the configured wallet but store the keys on app", false)); + hasWarning = true; } - result.Add("create-wallet", $"Create a new wallet to use on BTCPay Server and store the keys on app {warningPrefix}"); - result.Add("create-wallet-separate", "Create a new wallet to be used only on app"); + result.Add("create-wallet", ("Create a new wallet to use on BTCPay Server and store the keys on app", hasWarning)); + result.Add("create-wallet-separate", ("Create a new wallet to be used only on app", false)); return result; } } diff --git a/BTCPayApp.UI/Shared/Configuration/PairBTCPayServer.razor b/BTCPayApp.UI/Shared/Configuration/PairBTCPayServer.razor index 28fa107..37cf498 100644 --- a/BTCPayApp.UI/Shared/Configuration/PairBTCPayServer.razor +++ b/BTCPayApp.UI/Shared/Configuration/PairBTCPayServer.razor @@ -2,6 +2,9 @@ @using BTCPayApp.CommonServer @using BTCPayApp.Core @using System.Net.Http.Json +@using BTCPayApp.UI.Features +@inject IDispatcher Dispatcher +@inject IState State @if (Result is null) { @@ -12,10 +15,6 @@ Submit - @if (Loading) - { - - } @@ -45,7 +44,6 @@ else if (Result.StoreId is null) } } - private bool Loading { get; set; } private ValidationEditContext _validationEditContext { get; set; } private PairSuccessResult? Result { get; set; } @@ -63,9 +61,8 @@ else if (Result.StoreId is null) { try { - Loading = true; - var client = HttpClientFactory.CreateClient(); + Dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.PairConfig, true)); var response = await client.GetAsync(PairingUrl); response.EnsureSuccessStatusCode(); Result = await response.Content.ReadFromJsonAsync(); @@ -89,7 +86,7 @@ else if (Result.StoreId is null) } finally { - Loading = false; + Dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.PairConfig, false)); } } @@ -99,5 +96,4 @@ else if (Result.StoreId is null) { throw new NotImplementedException(); } - } diff --git a/BTCPayApp.UI/Shared/Dashboard.razor b/BTCPayApp.UI/Shared/Dashboard.razor index 497c640..70e038c 100644 --- a/BTCPayApp.UI/Shared/Dashboard.razor +++ b/BTCPayApp.UI/Shared/Dashboard.razor @@ -4,6 +4,7 @@ @using Microsoft.AspNetCore.SignalR.Client @using BTCPayApp.UI.Features @using BTCPayApp.UI.Pages +@using BTCPayApp.Core @inherits Fluxor.Blazor.Web.Components.FluxorComponent Dashboard @@ -28,10 +29,10 @@ else if (State.Value.PairConfig is not null) } else { - -
+ +
No BTCPay Server paired. - + Configure connection
@@ -48,65 +49,73 @@ else if (State.Value.WalletConfig is not null) } else { - -
+ +
Your wallet is not configured. - + Set up a wallet
} -Lightning Node: @State.Value.LightningNodeState +@if (State.Value.Loading.Contains(RootState.LoadingHandles.LightningState)) +{ + Lightning node loading. +} +else +{ + Your Lightning node is @LightningStatus +} - - @if (State.Value.Loading.Contains(RootState.LoadingHandles.TransactionState)) +@if (State.Value.Loading.Contains(RootState.LoadingHandles.TransactionState)) +{ + Transactions loading. +} +else +{ + Transactions + @if (OnChainTransactionsState.Value.Error is not false) { - + +
+ There was an error loading your transactions. + + Retry + +
+
} - else + else if (OnChainTransactionsState.Value.AllTransactions?.Any() is true) { - @if (OnChainTransactionsState.Value.Error is not false) - { - -
- There was an error loading your transactions. - - Retry - -
-
- } - - @if (OnChainTransactionsState.Value.AllTransactions is not null) - { - - @foreach (var tx in OnChainTransactionsState.Value.AllTransactions) - { - - -
-
- @tx.Value.Id - @tx.Value.Timestamp -
-
- @tx.Value.Balance - @tx.Value.Status -
+ + @foreach (var tx in OnChainTransactionsState.Value.AllTransactions) + { + + +
+
+ @tx.Value.Id + @tx.Value.Timestamp
- - - } - - - Refresh - - } +
+ @tx.Value.Balance + @tx.Value.Status +
+
+
+
+ } +
+ + Refresh + } - - + else + { + There are no transactions, yet. + } +} @code { private string ConnectionStatus => State.Value.BTCPayServerConnectionState?.ToString().ToLowerInvariant() ?? "not connected"; @@ -118,6 +127,24 @@ else _ => Severity.Warning }; + private string LightningStatus => State.Value.LightningNodeState switch { + + LightningNodeState.NotConfigured => "not configured", + LightningNodeState.WaitingForBackend => "waiting for the backend", + LightningNodeState.ShuttingDown => "shutting down", + LightningNodeState.Error => "in error state", + _ => State.Value.LightningNodeState.ToString().ToLowerInvariant() + }; + + private Severity LightningSeverity => State.Value.LightningNodeState switch { + LightningNodeState.Bootstrapping => Severity.Info, + LightningNodeState.Starting => Severity.Info, + LightningNodeState.WaitingForBackend => Severity.Info, + LightningNodeState.Connected => Severity.Success, + LightningNodeState.Error => Severity.Error, + _ => Severity.Warning + }; + protected override Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) return base.OnAfterRenderAsync(firstRender); diff --git a/BTCPayApp.UI/Shared/Onboarding.razor b/BTCPayApp.UI/Shared/Onboarding.razor index 3146d66..cf100f1 100644 --- a/BTCPayApp.UI/Shared/Onboarding.razor +++ b/BTCPayApp.UI/Shared/Onboarding.razor @@ -1,13 +1,13 @@ @using BTCPayApp.UI.Pages @inherits Fluxor.Blazor.Web.Components.FluxorComponent - +
Welcome To BTCPay Server - Free and open-source bitcoin point of sale. No fees, no third-party. + No fees, no third-party. All payments go through your node, running on your phone! Next @@ -28,7 +28,7 @@ Start Accepting Bitcoin Payments - With 0% Fees & No Third-party + Free and open-source bitcoin point of sale. With 0% Fees & No Third-party. Pair with BTCPay Server Use standalone @@ -36,42 +36,6 @@ -@*@if (Step == 0) -{ - Welcome To BTCPay Server - - Free and open-source bitcoin point of sale. No fees, no third-party. - All payments go through your node, running on your phone! - - - Next -} -else if (Step == 1) -{ - Keep your wallet and bitcoin secure, accounting and refunding - - Cloud backups, enhanced accounting functionality and ability to easily refund your customers - - - Next -} -else -{ - Start Accepting Bitcoin Payments - With 0% Fees & No Third-party - - - - Pair with BTCPay Server - - - Use standalone - - - - Next -}*@ - @code { private int Step { get; set; } = 0; diff --git a/BTCPayApp.UI/StateMiddleware.cs b/BTCPayApp.UI/StateMiddleware.cs index 09e092f..06599b0 100644 --- a/BTCPayApp.UI/StateMiddleware.cs +++ b/BTCPayApp.UI/StateMiddleware.cs @@ -61,6 +61,9 @@ private void ListenIn(IDispatcher dispatcher) _lightningNodeManager.StateChanged += (sender, args) => dispatcher.Dispatch(new RootState.LightningNodeStateUpdatedAction(args)); + if (_lightningNodeManager.State is not LightningNodeState.Connected) + dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.LightningState, true)); + if (_btcPayAppConfigManager.PairConfig is null) dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.PairConfig, true)); else @@ -79,6 +82,9 @@ private void ListenIn(IDispatcher dispatcher) dispatcher.Dispatch(new RootState.PairConfigLoadedAction(_btcPayAppConfigManager.PairConfig)); dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.PairConfig, false)); + dispatcher.Dispatch(new RootState.LightningNodeStateUpdatedAction(_lightningNodeManager.State)); + dispatcher.Dispatch(new RootState.LoadingAction(RootState.LoadingHandles.LightningState, false)); + dispatcher.Dispatch(new RootState.BTCPayConnectionUpdatedAction(_btcPayConnection.Connection?.State)); }); }