Skip to content

Conversation

@ichthus1604
Copy link
Contributor

@ichthus1604 ichthus1604 commented Nov 19, 2023

Okay, this PR is quite big.

Description

Both CurrencyEntryBox and DualCurrencyEntryBox have been completely rewritten.

The following changes have been made:

  • a CurrencyFormat model has been introduced, which Represents a specific Currency's Parsing and Formatting rules.

    • This also defines aspects such as CurrencyCode, MaxFractionalDigits, MaxIntegralDigits, etc.
    • there are 3 CurrencyFormats right now: CurrencyFormat.Btc, CurrencyFormat.Usd and CurrencyFormat.SatvByte
    • More could be introduced in the future to support other currencies.
  • CurrencyEntryBox now delegates all of the above aspects to the model, and deals only with user input, caret positioning, etc. It only deals with text and decimal Value property. it is up to the ViewModel to convert this numeric data into whatever it needs.

  • Both CurrencyEntryBox and DualCurrencyEntryBox are completely agnostic to aspects such as conversion rates, currencies, etc.

  • The clipboard handling logic has been moved to CurrencyEntryBoxClipboardBehavior. Once again this only deals with input and delegates logic to the CurrencyEntryBox.CurrencyFormat for parsing, etc.

    • The max amount logic depends on CurrencyEntryBox.MaxValue which gets updated (for instance in the Send View) accoding to the available balance and exchange rate. 
  • ClipboardObserver class has been removed.

  • DualCurrencyEntryBox no longer has a readonly state (and corresponding template). For cases where IsFixedAmount=true in the send dialog, the entry box gets replaced by a simple AmountControl which shows the amount as readonly text.

  • 2 new ViewModels have been introduced in the send screen:

    • CurrencyViewModel deals with a single currency input and its corresponding MaxValue (both in decimal format)
    • CurrencyConversionViewModel deals with BTC <-> USD conversion and also with left/right switching.

Results

  • All the input bugs and usability problems that appeared after Avalonia V11 migration are gone.

  • The general design is much cleaner. Spaghetti has been removed everywhere, and now each layer (UI, Models, ViewModel) deals only with its corresponding responsibility.

  • The above makes the design of DualCurrencyEntryBox extremely simple. It is just a container for the 2 currency inputs and the toggle button. It has only 76 lines of code now (down from 471 on master). The switching from left to right happens in the data, not the UI, this can be done because the UI elements are currency-agnostic.

  • Groundwork has been laid to enable supporting multiple currencies (other than USD) and also localization-sensitive aspects have been moved to CurrencyLocalization class.

  • ViewModels no longer need to deal with money amounts as strings but rather as decimal amounts, regardless of currency. This also helped clean up some logic in the VMs such as format validation, etc.

  • SendViewModel no longer deals with clipboard contents

  • DualCurrencyEntryBox now has only 6 lines of logic, dealing with focus.

  • CurrencyEntryBox no longer needs a specialized version of the paste command. Simple and standard copy and paste just works.

  • Most of the code has been thoroughly documented.

Testing

  • The following manual tests have been made:
    • text input, including selection
    • typing "." with an empty box results in "0."
    • caret positioning affected by formatting rules
    • not being able to enter more than the max number of integral digits and fractional digits (defined by CurrencyFormat)
    • clipboard logic
      • paste valid values for both currencies
      • paste invalid values for both currencies
      • paste non numerical text
      • paste using Ctrl+V and right click context menu option
    • clipboard auto suggestion logic:
      • for valid numerical values
      • for invalid numerical values
      • for valid amounts within the range defined by MaxValue property (bound to the available balance in the Send view)
      • for invalid amounts as per the above
    • left/right switching and its effects on keyboard focus
    • readonly amount in the send dialog
    • BTC only input in the send dialog when exchange rate is not available
    • send full balance by clicking in the balance text in send view
    • standalone uses of CurrencyEntryBox:
      • CustomFeeRateDialog
      • PlebStopThreshold
      • DustThreshold

Problems

While writing this PR, I found and reported AvaloniaUI/Avalonia#13648. There may be other issues (mostly related to caret positioning) related to this.

There are also stylistic things in the code, such as CurrencyConversionViewModel relying too much on the _isUpdating flag. Maybe @SuperJMN can come up with a cleaner way to handle this using Rx.

Next steps

Copy link
Contributor

@RolandUI RolandUI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't review this properly. Will do another round tomorrow.

  • Exception when selection a part of Dust Threshold and copying:
2024-02-04 15:50:41.625 [1] ERROR       CurrencyInputViewModel.CopySelectionToClipboardAsync (504)      System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
   at System.String.ThrowSubstringArgumentOutOfRange(Int32 startIndex, Int32 length)
   at System.String.Substring(Int32 startIndex, Int32 length)
   at WalletWasabi.Fluent.ViewModels.Wallets.Send.CurrencyConversion.CurrencyInputViewModel.CopySelectionToClipboardAsync() in WalletWasabi.Fluent\ViewModels\Wallets\Send\CurrencyConversion\CurrencyInputViewModel.cs:line 497

Comment on lines +13 to +25
public async Task<string?> TryGetTextAsync()
{
try
{
return await GetTextAsync();
}
catch (Exception ex)
{
Logger.LogError(ex);
}

return null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this for debugging?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. This is used because I've noticed there are times when GetTextAsync() crashes inside an Avalonia method.
I decided to just ignore the exception and retry later.

@turbolay
Copy link
Collaborator

turbolay commented Feb 4, 2024

Please test carefully this branch on Mac because since this message:

Tested and works well enough for the release. Will review the code tomorrow.

I tested twice and twice I had a crash in the first few seconds of using the feature

First was the Clipboard, this is now fixed
Now this, in this video I'm pressing only one time 0, it writes it twice, when I press delete it moves the cursor weirdly, when I press delete again it delete both 0 weirdly (so I can even write only one 0), and when I press . it crashes

CleanShot.2024-02-04.at.09.09.05.mp4
Program.Main (75)	System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
   at System.String.ThrowSubstringArgumentOutOfRange(Int32 startIndex, Int32 length)
   at System.String.Substring(Int32 startIndex, Int32 length)
   at WalletWasabi.Fluent.ViewModels.Wallets.Send.CurrencyConversion.CurrencyInputViewModel.Insert(String text) in WalletWasabi.Fluent/ViewModels/Wallets/Send/CurrencyConversion/CurrencyInputViewModel.cs:line 60
   at WalletWasabi.Fluent.ViewModels.Wallets.Send.CurrencyConversion.CurrencyInputViewModel.InsertDecimalSeparator() in WalletWasabi.Fluent/ViewModels/Wallets/Send/CurrencyConversion/CurrencyInputViewModel.cs:line 103
   at WalletWasabi.Fluent.Controls.CurrencyEntryBox.CustomOnKeyDown(Object sender, KeyEventArgs e) in WalletWasabi.Fluent/Controls/CurrencyEntryBox/CurrencyEntryBox.axaml.cs:line 281

@RolandUI
Copy link
Contributor

RolandUI commented Feb 5, 2024

I cannot reproduce those issues on Win11, @wieslawsoltes @ichthus1604 you guys have Mac, please test it deeply. @MarnixCroes Could you test this on Linux, just to make sure...

@wieslawsoltes
Copy link
Contributor

I cannot reproduce those issues on Win11, @wieslawsoltes @ichthus1604 you guys have Mac, please test it deeply. @MarnixCroes Could you test this on Linux, just to make sure...

Its regression in Avalonia 11.0.7, in 11.0.6 it works

@ichthus1604
Copy link
Contributor Author

@soosr

Exception when selection a part of Dust Threshold and copying:

Fixed.

Copy link
Contributor

@RolandUI RolandUI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't work on osx:

  • Entering any number for the first time into the field once, ends up being entered twice.
    • Moving the caret with left and right arrow is glitchy at this state.
    • Entering one additional number results in exception:
    2024-02-06 09:27:13.698 [1] ERROR	CurrencyInputViewModel.Insert (84)	System.ArgumentOutOfRangeException: Index and length must refer to a location within the string. (Parameter 'length')
    at System.String.ThrowSubstringArgumentOutOfRange(Int32 startIndex, Int32 length)
    at System.String.Substring(Int32 startIndex, Int32 length)
    at WalletWasabi.Fluent.ViewModels.Wallets.Send.CurrencyConversion.CurrencyInputViewModel.Insert(String text) in WalletWasabi.Fluent/ViewModels/Wallets/Send/CurrencyConversion/CurrencyInputViewModel.cs:line 62
    
    • Removing one number cause a same exception.
  • Pressing . results in 0.. which probably the same issue as before.
  • (osx, windows) Caret's position should be the very end, when clicking on the amount text on the top right of Send dialog.
  • Clicking on the suggested amount flyout doesn't work for BTC field. (work well for USD)
  • Entering a amount into USD field, then clicking on the BTC field (the input is not selected) then pressing BACKSPACE removes the whole input.
    • Moving the caret left then right solves the issue and backspace work as expected.

@turbolay
Copy link
Collaborator

turbolay commented Feb 6, 2024

It's working now, well done! There are still some bugs but it's correct. One annoying bug: the first time I focus and press CMD + V to paste, it doesn't work. Same goes for CMD + A

@RolandUI
Copy link
Contributor

RolandUI commented Feb 7, 2024

  • Mac Clicking on the suggested amount Flyout doesn't work on the BTC field (works well on USD)
  • Mac CMD + V doesn't work. CMD + V + V works for pasting
  • Mac CMD + A doesn't work. CMD + A + A works for selecting all
    • Mac Pasting 0.00023 then selecting all, doesn't select the whole input, last char is missing.
  • Mac Selecting with mouse doesn't work. (double click, select all works)
  • Mac Cannot start input with 0.
    • Actually cannot manually type in 0 at all.
  • Windows After Entering 0 the caret is visually in the wrong position (its in the beginning), although adding new numbers goes after 0.
    • Actually if you start typing, you will see the caret most of the time is before the last char.
    • Can repro on the USD field too.
  • Mac Selecting with shift + arrow, the first action doesn't do anything.

@SuperJMN
Copy link
Contributor

SuperJMN commented Feb 7, 2024

I've tested this in Linux (444b629) and by far, the worst UX problem is:

  • Given blank input, type any digit. Delete it. Type any digit again. The caret will position incorrectly on the left side of the just typed digit.
    image

@RolandUI
Copy link
Contributor

RolandUI commented Feb 8, 2024

Converting to draft due to mac issues

@RolandUI RolandUI marked this pull request as draft February 8, 2024 07:31
@stale
Copy link

stale bot commented Apr 22, 2024

This has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UI] Entering amount to send bug [VDG] Half selected amount [VDG] CurrencyEntryBox is not consistent

8 participants