From ad25feda6bfac4b4779b92500b01d341931dcbb0 Mon Sep 17 00:00:00 2001 From: Rudy Huyn Date: Tue, 16 Apr 2019 11:29:43 -0700 Subject: [PATCH] Keep input when users refresh currency rates (#369) Fixes #260 Description of the changes: prevent UnitConverterViewModel to reset values when users click on update rates. recompute UnitConverter's caches (m_ratioMap and m_categoryToUnits) once rates are updated (but check first if the user did/didn't change the category) How changes were validated: Manually tested with fake currency rates (HTTP responses modified on the fly via FiddlerCore) Verified that it works no matter the selected field (From or To) Verified that the currencies selected are kept after a refresh --- src/CalcManager/UnitConverter.cpp | 41 +++++++++++-------- src/CalcManager/UnitConverter.h | 8 ++-- src/CalcViewModel/UnitConverterViewModel.cpp | 12 ++++-- src/CalcViewModel/UnitConverterViewModel.h | 2 + .../UnitConverterViewModelUnitTests.h | 5 ++- 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/CalcManager/UnitConverter.cpp b/src/CalcManager/UnitConverter.cpp index 0548719..718e47f 100644 --- a/src/CalcManager/UnitConverter.cpp +++ b/src/CalcManager/UnitConverter.cpp @@ -63,7 +63,8 @@ UnitConverter::UnitConverter(_In_ const shared_ptr& dataLo unquoteConversions[L"{sc}"] = L';'; unquoteConversions[L"{lb}"] = LEFTESCAPECHAR; unquoteConversions[L"{rb}"] = RIGHTESCAPECHAR; - Reset(); + ClearValues(); + ResetCategoriesAndRatios(); } void UnitConverter::Initialize() @@ -75,7 +76,7 @@ bool UnitConverter::CheckLoad() { if (m_categories.empty()) { - Reset(); + ResetCategoriesAndRatios(); } return !m_categories.empty(); } @@ -152,7 +153,6 @@ void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType Calculate(); UpdateCurrencySymbols(); - UpdateViewModel(); } /// @@ -336,7 +336,8 @@ wstring UnitConverter::Serialize() /// wstring holding the serialized data. If it does not have expected number of parameters, we will ignore it void UnitConverter::DeSerialize(const wstring& serializedData) { - Reset(); + ClearValues(); + ResetCategoriesAndRatios(); if (serializedData.empty()) { @@ -615,7 +616,7 @@ void UnitConverter::SendCommand(Command command) clearFront = false; clearBack = false; ClearValues(); - Reset(); + ResetCategoriesAndRatios(); break; default: @@ -634,8 +635,6 @@ void UnitConverter::SendCommand(Command command) } Calculate(); - - UpdateViewModel(); } /// @@ -824,19 +823,16 @@ vector> UnitConverter::CalculateSuggested() returnVector.push_back(whimsicalReturnVector.at(0)); } - // - return returnVector; } /// -/// Resets the converter to its initial state +/// Resets categories and ratios /// -void UnitConverter::Reset() +void UnitConverter::ResetCategoriesAndRatios() { m_categories = m_dataLoader->LoadOrderedCategories(); - ClearValues(); m_switchedActive = false; if (m_categories.empty()) @@ -881,7 +877,6 @@ void UnitConverter::Reset() } InitializeSelectedUnits(); - Calculate(); } /// @@ -972,11 +967,21 @@ bool UnitConverter::AnyUnitIsEmpty() /// void UnitConverter::Calculate() { - unordered_map conversionTable = m_ratioMap[m_fromType]; - double returnValue = stod(m_currentDisplay); - if (AnyUnitIsEmpty() || (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0)) + if (AnyUnitIsEmpty()) { m_returnDisplay = m_currentDisplay; + m_returnHasDecimal = m_currentHasDecimal; + TrimString(m_returnDisplay); + UpdateViewModel(); + return; + } + + unordered_map conversionTable = m_ratioMap[m_fromType]; + double returnValue = stod(m_currentDisplay); + if (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0) + { + m_returnDisplay = m_currentDisplay; + m_returnHasDecimal = m_currentHasDecimal; TrimString(m_returnDisplay); } else @@ -1015,9 +1020,9 @@ void UnitConverter::Calculate() m_returnDisplay = returnString; TrimString(m_returnDisplay); } + m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos); } - - m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos); + UpdateViewModel(); } /// diff --git a/src/CalcManager/UnitConverter.h b/src/CalcManager/UnitConverter.h index 4e130d1..010216f 100644 --- a/src/CalcManager/UnitConverter.h +++ b/src/CalcManager/UnitConverter.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once @@ -195,6 +195,8 @@ namespace UnitConversionManager virtual void SetViewModelCallback(_In_ const std::shared_ptr& newCallback) = 0; virtual void SetViewModelCurrencyCallback(_In_ const std::shared_ptr& newCallback) = 0; virtual concurrency::task> RefreshCurrencyRatios() = 0; + virtual void Calculate() = 0; + virtual void ResetCategoriesAndRatios() = 0; }; class UnitConverter : public IUnitConverter, public std::enable_shared_from_this @@ -218,6 +220,8 @@ namespace UnitConversionManager void SetViewModelCallback(_In_ const std::shared_ptr& newCallback) override; void SetViewModelCurrencyCallback(_In_ const std::shared_ptr& newCallback) override; concurrency::task> RefreshCurrencyRatios() override; + void Calculate() override; + void ResetCategoriesAndRatios() override; // IUnitConverter static std::vector StringToVector(const std::wstring& w, const wchar_t * delimiter, bool addRemainder = false); @@ -228,9 +232,7 @@ namespace UnitConversionManager bool CheckLoad(); double Convert(double value, ConversionData conversionData); std::vector> CalculateSuggested(); - void Reset(); void ClearValues(); - void Calculate(); void TrimString(std::wstring& input); void InitializeSelectedUnits(); std::wstring RoundSignificant(double num, int numSignificant); diff --git a/src/CalcViewModel/UnitConverterViewModel.cpp b/src/CalcViewModel/UnitConverterViewModel.cpp index 76d9aa3..446ae58 100644 --- a/src/CalcViewModel/UnitConverterViewModel.cpp +++ b/src/CalcViewModel/UnitConverterViewModel.cpp @@ -165,12 +165,16 @@ void UnitConverterViewModel::PopulateData() } void UnitConverterViewModel::OnCategoryChanged(Object^ parameter) +{ + m_model->SendCommand(UCM::Command::Clear); + ResetCategory(); +} + +void UnitConverterViewModel::ResetCategory() { UCM::Category currentCategory = CurrentCategory->GetModelCategory(); IsCurrencyCurrentCategory = currentCategory.id == NavCategory::Serialize(ViewMode::Currency); - m_model->SendCommand(UCM::Command::Clear); - m_isInputBlocked = false; SetSelectedUnits(); @@ -706,7 +710,9 @@ void UnitConverterViewModel::OnCurrencyDataLoadFinished(bool didLoad) { m_isCurrencyDataLoaded = true; CurrencyDataLoadFailed = !didLoad; - ResetView(); + m_model->ResetCategoriesAndRatios(); + m_model->Calculate(); + ResetCategory(); StringReference key = didLoad ? UnitConverterResourceKeys::CurrencyRatesUpdated : UnitConverterResourceKeys::CurrencyRatesUpdateFailed; String^ announcement = AppResourceProvider::GetInstance().GetResourceString(key); diff --git a/src/CalcViewModel/UnitConverterViewModel.h b/src/CalcViewModel/UnitConverterViewModel.h index 5a98238..2c6c8af 100644 --- a/src/CalcViewModel/UnitConverterViewModel.h +++ b/src/CalcViewModel/UnitConverterViewModel.h @@ -223,6 +223,7 @@ namespace CalculatorApp void UpdateValue2AutomationName(); Platform::String^ Serialize(); void Deserialize(Platform::String^ state); + void ResetCategoriesAndRatio(); // Saving And Restoring User Preferences of Category and Associated-Units across Sessions. void SaveUserPreferences(); @@ -263,6 +264,7 @@ namespace CalculatorApp void RefreshSupplementaryResults(); void UpdateInputBlocked(_In_ const std::wstring& currencyInput); bool UnitsAreValid(); + void ResetCategory(); void OnButtonPressed(Platform::Object^ parameter); Platform::String^ ConvertToLocalizedString(const std::wstring& stringToLocalize, bool allowPartialStrings); diff --git a/src/CalculatorUnitTests/UnitConverterViewModelUnitTests.h b/src/CalculatorUnitTests/UnitConverterViewModelUnitTests.h index 1e1b57c..903fd07 100644 --- a/src/CalculatorUnitTests/UnitConverterViewModelUnitTests.h +++ b/src/CalculatorUnitTests/UnitConverterViewModelUnitTests.h @@ -42,11 +42,14 @@ namespace CalculatorUnitTests void SendCommand(UCM::Command command) override; void SetViewModelCallback(const std::shared_ptr& newCallback) override; void SetViewModelCurrencyCallback(_In_ const std::shared_ptr& /*newCallback*/) override {} + void Calculate() override {} + void ResetCategoriesAndRatios() override{} concurrency::task> RefreshCurrencyRatios() override { - co_return std::make_pair(L"", L""); + co_return std::make_pair(true, L""); } + UINT m_initCallCount; UINT m_getCategoriesCallCount; UINT m_setCurrentCategoryCallCount;