-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor UI and State Management for Checkbox and Button Handling #130
Changes from 6 commits
34fc20a
66f6acb
5c32053
6d9d3ea
3354f19
6947c72
9c462d6
33a503c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,7 +85,7 @@ | |
@if (stageisActive) | ||
{ | ||
|
||
<button class="btn @((noCoinsToClaim) ? "btn-light" : "btn-success")" disabled="@noCoinsToClaim" @onclick="() => ClaimCoinsCheckPassword(stage.StageIndex)"> | ||
<button class="btn @((noCoinsToClaim) ? "btn-light" : "btn-success")" disabled="@((noCoinsToClaim || !IsCheckboxSelectedForStage(stage.StageIndex)))" @onclick="() => ClaimCoinsCheckPassword(stage.StageIndex)"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be much simplified, when we expand another stage we clear the dictionary so there will only be items for a particular stage right? so you just need to check if the dictionary There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
@if (stage.StagePinner) | ||
{ | ||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> | ||
|
@@ -122,22 +122,22 @@ | |
<div class="mt-3"> | ||
@foreach (var transaction in stage.Items) | ||
{ | ||
bool isTicked = selected.ContainsKey(transaction.Trxid); | ||
string statusClass = transaction.IsSpent ? "bg-warning text-dark" : "bg-success text-light"; | ||
string statusText = transaction.IsSpent ? "Spent" : "Unspent"; | ||
|
||
<div class="d-flex mb-2"> | ||
<input id="@transaction.Trxid" type="checkbox" disabled="@(!stageisActive || transaction.IsSpent)" value="@isTicked" @onclick="() => HandleCheckboxChange(transaction.Trxid)" /> | ||
<label for="@transaction.Trxid"> | ||
@transaction.Amount @network.CoinTicker - utxo : | ||
<span style="cursor: pointer; text-decoration: underline;" @onclick="() => CopyTRXToClipboard(transaction.Trxid)">@transaction.Trxid</span> -@transaction.Outputindex | ||
<span class="p-1 rounded @statusClass"> | ||
@statusText | ||
</span> | ||
</label> | ||
</div> | ||
|
||
bool isTicked = IsUtxoSelected(transaction.Trxid, transaction.Outputindex); | ||
string statusClass = transaction.IsSpent ? "bg-warning text-dark" : "bg-success text-light"; | ||
string statusText = transaction.IsSpent ? "Spent" : "Unspent"; | ||
|
||
<div class="d-flex mb-2"> | ||
<input id="@transaction.Trxid" type="checkbox" disabled="@(!stageisActive || transaction.IsSpent)" checked="@isTicked" @onclick="() => HandleCheckboxChange(transaction.Trxid, transaction.Outputindex)" /> | ||
<label for="@transaction.Trxid"> | ||
@transaction.Amount @network.CoinTicker - utxo : | ||
<span style="cursor: pointer; text-decoration: underline;" @onclick="() => CopyTRXToClipboard(transaction.Trxid)">@transaction.Trxid</span> -@transaction.Outputindex | ||
<span class="p-1 rounded @statusClass"> | ||
@statusText | ||
</span> | ||
</label> | ||
</div> | ||
} | ||
|
||
</div> | ||
} | ||
</div> | ||
|
@@ -174,11 +174,19 @@ | |
<hr> | ||
|
||
<h6 class="mt-3 mb-2">Stages</h6> | ||
@foreach (var item in selected) | ||
@foreach (var utxo in selectedUtxos) | ||
{ | ||
<p style="font-size: 0.7em;" class="mb-1">@item.Key</p> | ||
if (utxo.Value) // check if the UTXO is selected | ||
{ | ||
var utxoKey = utxo.Key; | ||
|
||
var stageIndex = GetStageIndexForUtxo(utxoKey); | ||
|
||
<p style="font-size: 0.7em;" class="mb-1">Stage: @stageIndex, Transaction: @utxoKey.Trxid, Output Index: @utxoKey.Outputindex</p> | ||
} | ||
} | ||
|
||
|
||
<hr> | ||
|
||
<p class="mt-3">Are you sure you want to continue?</p> | ||
|
@@ -255,7 +263,7 @@ | |
|
||
List<(Transaction Transaction, string TrxId)> transactions = new(); | ||
|
||
Dictionary<string, string> selected = new(); | ||
Dictionary<UtxoKey, bool> selectedUtxos = new Dictionary<UtxoKey, bool>(); | ||
|
||
public class StageData | ||
{ | ||
|
@@ -480,15 +488,14 @@ | |
{ | ||
passwordComponent.ShowPassword(async () => | ||
{ | ||
await ClaimCoins(stageId); ; | ||
await ClaimCoins(stageId); | ||
}); | ||
} | ||
} | ||
|
||
private async Task ClaimCoins(int stageId) | ||
{ | ||
var stage = stageDatas.First(s => s.StageIndex == stageId); | ||
|
||
stage.StagePinner = true; | ||
|
||
StateHasChanged(); | ||
|
@@ -507,13 +514,15 @@ | |
|
||
founderContext = new FounderContext { ProjectInfo = project, ProjectSeeders = new ProjectSeeders() }; | ||
|
||
foreach (var item in selected) | ||
foreach (var utxo in selectedUtxos.Where(kv => GetStageIndexForUtxo(kv.Key) == stageId && kv.Value)) | ||
{ | ||
var trx = transactions.First(f => f.TrxId == item.Key); | ||
var trxId = utxo.Key.Trxid; | ||
var trx = transactions.First(f => f.TrxId == trxId); | ||
|
||
founderContext.InvestmentTrasnactionsHex.Add(trx.Transaction.ToHex(network.Consensus.ConsensusFactory)); | ||
} | ||
|
||
|
||
var accountInfo = storage.GetAccountInfo(network.Name); | ||
var address = accountInfo.GetNextReceiveAddress(); | ||
var addressScript = BitcoinWitPubKeyAddress.Create(address, network).ScriptPubKey; | ||
|
@@ -533,12 +542,19 @@ | |
} | ||
finally | ||
{ | ||
CalculateTotalValues(); | ||
|
||
if (selectedUtxos.Keys.Any(utxoKey => GetStageIndexForUtxo(utxoKey) == selectedStageId)) | ||
{ | ||
selectedUtxos.Clear(); | ||
} | ||
stage.StagePinner = false; | ||
} | ||
|
||
StateHasChanged(); | ||
} | ||
|
||
|
||
private async Task FeeRangeChanged(ChangeEventArgs e) | ||
{ | ||
var selectedItem = e.Value?.ToString(); | ||
|
@@ -628,20 +644,39 @@ | |
private void Expand(int stageId) | ||
{ | ||
expandedStageId = expandedStageId == stageId ? null : stageId; | ||
selectedUtxos.Clear(); | ||
} | ||
|
||
private void HandleCheckboxChange(string trxId) | ||
private void HandleCheckboxChange(string trxId, int outputIndex) | ||
{ | ||
var key = new UtxoKey(trxId, outputIndex); | ||
|
||
if (selected.ContainsKey(trxId)) | ||
if (selectedUtxos.ContainsKey(key)) | ||
{ | ||
selected.Remove(trxId); | ||
selectedUtxos.Remove(key); | ||
} | ||
else | ||
{ | ||
selected.Add(trxId, null); | ||
selectedUtxos[key] = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will always be true, we wont have a case that the value is false right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removing the key means it no longer exists in the dictionary, so there isn't a false value associated with it? |
||
} | ||
} | ||
|
||
private bool IsUtxoSelected(string trxId, int outputIndex) | ||
{ | ||
return selectedUtxos.ContainsKey(new UtxoKey(trxId, outputIndex)); | ||
} | ||
|
||
private int GetStageIndexForUtxo(UtxoKey utxoKey) | ||
{ | ||
return stageDatas.First(stage => stage.Items.Any(item => item.Trxid == utxoKey.Trxid && item.Outputindex == utxoKey.Outputindex)).StageIndex; | ||
} | ||
|
||
|
||
private bool IsCheckboxSelectedForStage(int stageIndex) | ||
{ | ||
return selectedUtxos.Any(utxo => GetStageIndexForUtxo(utxo.Key) == stageIndex && utxo.Value); | ||
} | ||
|
||
|
||
private async Task CopyTRXToClipboard(string trxData) | ||
{ | ||
|
@@ -653,4 +688,31 @@ | |
await _clipboardService.WriteTextAsync(trxData); | ||
StateHasChanged(); | ||
} | ||
|
||
public struct UtxoKey | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is already such a type its called There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will check it out 👍 |
||
{ | ||
public string Trxid { get; set; } | ||
public int Outputindex { get; set; } | ||
|
||
public UtxoKey(string trxid, int outputindex) | ||
{ | ||
Trxid = trxid; | ||
Outputindex = outputindex; | ||
} | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
if (!(obj is UtxoKey)) | ||
return false; | ||
|
||
var key = (UtxoKey)obj; | ||
return Trxid == key.Trxid && Outputindex == key.Outputindex; | ||
} | ||
|
||
public override int GetHashCode() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah I see you need to compile a hashcode for the dictionary unique key. |
||
{ | ||
return HashCode.Combine(Trxid, Outputindex); | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I notice your IDE will align lines incorrectly, this line of code should be pushed one tab to the right, I think its an IDE issue