-
Notifications
You must be signed in to change notification settings - Fork 552
[UI] Refactor CurrencyEntryBox #11966
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
base: master
Are you sure you want to change the base?
[UI] Refactor CurrencyEntryBox #11966
Conversation
RolandUI
left a comment
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.
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
| public async Task<string?> TryGetTextAsync() | ||
| { | ||
| try | ||
| { | ||
| return await GetTextAsync(); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Logger.LogError(ex); | ||
| } | ||
|
|
||
| return null; | ||
| } |
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.
Was this for debugging?
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.
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.
WalletWasabi.Fluent/ViewModels/Wallets/Send/CurrencyConversion/CurrencyInputViewModel.cs
Outdated
Show resolved
Hide resolved
|
Please test carefully this branch on Mac because since this message:
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 CleanShot.2024-02-04.at.09.09.05.mp4 |
|
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 |
|
@soosr
Fixed. |
RolandUI
left a comment
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.
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 in0..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.
|
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 |
|
|
I've tested this in Linux (444b629) and by far, the worst UX problem is: |
|
Converting to draft due to mac issues |
|
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. |

Okay, this PR is quite big.
Description
Both
CurrencyEntryBoxandDualCurrencyEntryBoxhave been completely rewritten.The following changes have been made:
a
CurrencyFormatmodel has been introduced, which Represents a specific Currency's Parsing and Formatting rules.CurrencyFormat.Btc,CurrencyFormat.UsdandCurrencyFormat.SatvByteCurrencyEntryBoxnow delegates all of the above aspects to the model, and deals only with user input, caret positioning, etc. It only deals with text anddecimalValue property. it is up to the ViewModel to convert this numeric data into whatever it needs.Both
CurrencyEntryBoxandDualCurrencyEntryBoxare 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 theCurrencyEntryBox.CurrencyFormatfor parsing, etc.CurrencyEntryBox.MaxValuewhich gets updated (for instance in the Send View) accoding to the available balance and exchange rate.ClipboardObserverclass has been removed.DualCurrencyEntryBoxno longer has areadonlystate (and corresponding template). For cases whereIsFixedAmount=truein the send dialog, the entry box gets replaced by a simpleAmountControlwhich shows the amount as readonly text.2 new ViewModels have been introduced in the send screen:
CurrencyViewModeldeals with a single currency input and its correspondingMaxValue(both in decimal format)CurrencyConversionViewModeldeals withBTC <-> USDconversion and also with left/right switching.Results
All the input bugs and usability problems that appeared after Avalonia V11 migration are gone.
CurrencyLocalization.LocalizedFormat()for details.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
DualCurrencyEntryBoxextremely 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
CurrencyLocalizationclass.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.
SendViewModelno longer deals with clipboard contentsDualCurrencyEntryBoxnow has only 6 lines of logic, dealing with focus.CurrencyEntryBoxno 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
CurrencyFormat)MaxValueproperty (bound to the available balance in the Send view)CurrencyEntryBox:CustomFeeRateDialogPlebStopThresholdDustThresholdProblems
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
CurrencyConversionViewModelrelying too much on the_isUpdatingflag. Maybe @SuperJMN can come up with a cleaner way to handle this using Rx.Next steps
12,355.88is not covered and will not be parseable using the current logic)