-
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 all 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 |
---|---|---|
|
@@ -75,7 +75,7 @@ | |
bool stageisActive = stage.Stage.ReleaseDate < DateTime.UtcNow; | ||
var investedCount = stage.Items.Count(c => c.IsSpent == false); | ||
var investedAmount = stage.Items.Where(c => c.IsSpent == false).Sum(c => c.Amount); | ||
bool noCoinsToClaim = investedCount == 0 || stage.StagePinner == true; | ||
bool noCoinsToClaim = investedCount == 0 || stage.StageSpinner == true; | ||
|
||
|
||
<div class="mb-4"> | ||
|
@@ -85,8 +85,8 @@ | |
@if (stageisActive) | ||
{ | ||
|
||
<button class="btn @((noCoinsToClaim) ? "btn-light" : "btn-success")" disabled="@noCoinsToClaim" @onclick="() => ClaimCoinsCheckPassword(stage.StageIndex)"> | ||
@if (stage.StagePinner) | ||
<button class="btn @((noCoinsToClaim) ? "btn-light" : "btn-success")" disabled="@((noCoinsToClaim || !IsCheckboxSelectedForStage(stage.StageIndex)))" @onclick="() => ClaimCoinsCheckPassword(stage.StageIndex)"> | ||
@if (stage.StageSpinner) | ||
{ | ||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> | ||
<span>Building trx...</span> | ||
|
@@ -122,12 +122,12 @@ | |
<div class="mt-3"> | ||
@foreach (var transaction in stage.Items) | ||
{ | ||
bool isTicked = selected.ContainsKey(transaction.Trxid); | ||
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)" value="@isTicked" @onclick="() => HandleCheckboxChange(transaction.Trxid)" /> | ||
<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 | ||
|
@@ -136,8 +136,8 @@ | |
</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,14 +263,14 @@ | |
|
||
List<(Transaction Transaction, string TrxId)> transactions = new(); | ||
|
||
Dictionary<string, string> selected = new(); | ||
Dictionary<UtxoKey, bool> selectedUtxos = new Dictionary<UtxoKey, bool>(); | ||
|
||
public class StageData | ||
{ | ||
public int StageIndex; | ||
public Stage Stage; | ||
public List<StageDataTrx> Items = new(); | ||
public bool StagePinner = false; | ||
public bool StageSpinner = false; | ||
} | ||
|
||
public class StageDataTrx | ||
|
@@ -425,8 +433,6 @@ | |
} | ||
} | ||
|
||
|
||
|
||
private async Task CheckSpentFund() | ||
{ | ||
List<QueryTransaction> trxs = new(); | ||
|
@@ -480,16 +486,15 @@ | |
{ | ||
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; | ||
stage.StageSpinner = true; | ||
|
||
StateHasChanged(); | ||
await Task.Delay(10); | ||
|
@@ -507,13 +512,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 +540,19 @@ | |
} | ||
finally | ||
{ | ||
stage.StagePinner = false; | ||
CalculateTotalValues(); | ||
|
||
if (selectedUtxos.Keys.Any(utxoKey => GetStageIndexForUtxo(utxoKey) == selectedStageId)) | ||
{ | ||
selectedUtxos.Clear(); | ||
} | ||
stage.StageSpinner = false; | ||
} | ||
|
||
StateHasChanged(); | ||
} | ||
|
||
|
||
private async Task FeeRangeChanged(ChangeEventArgs e) | ||
{ | ||
var selectedItem = e.Value?.ToString(); | ||
|
@@ -628,20 +642,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 +686,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.
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
selectedUtxos
has items in it, correct me if I am wrong.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.
noCoinsToClaim
is determined byinvestedCount == 0
orstage.StagePinner == true
.there might be a scenario where
selectedUtxos
has values for stage 2. In this case, theclaimCoins
option for stage 1 won't be disabled.providing the
stageIndex
and the relevant method, we can handle the logic for each stage appropriately.