This commit is contained in:
Tian Liao 2024-11-26 15:02:29 +08:00
commit 80bbb1ad81
12 changed files with 183 additions and 205 deletions

View file

@ -171,8 +171,8 @@ void ApplicationViewModel::OnModeChanged()
if (!m_ConverterViewModel) if (!m_ConverterViewModel)
{ {
auto dataLoader = std::make_shared<UnitConverterDataLoader>(ref new GeographicRegion()); auto dataLoader = std::make_shared<UnitConverterDataLoader>(ref new GeographicRegion());
auto currencyDataLoader = std::make_shared<CurrencyDataLoader>(std::make_unique<CurrencyHttpClient>()); m_ConverterViewModel =
m_ConverterViewModel = ref new UnitConverterViewModel(std::make_shared<UnitConversionManager::UnitConverter>(dataLoader, currencyDataLoader)); ref new UnitConverterViewModel(std::make_shared<UnitConversionManager::UnitConverter>(dataLoader, std::make_shared<CurrencyDataLoader>()));
} }
m_ConverterViewModel->Mode = m_mode; m_ConverterViewModel->Mode = m_mode;

View file

@ -325,7 +325,6 @@
<ClInclude Include="Common\Utils.h" /> <ClInclude Include="Common\Utils.h" />
<ClInclude Include="DataLoaders\CurrencyDataLoader.h" /> <ClInclude Include="DataLoaders\CurrencyDataLoader.h" />
<ClInclude Include="DataLoaders\CurrencyHttpClient.h" /> <ClInclude Include="DataLoaders\CurrencyHttpClient.h" />
<ClInclude Include="DataLoaders\ICurrencyHttpClient.h" />
<ClInclude Include="DataLoaders\UnitConverterDataConstants.h" /> <ClInclude Include="DataLoaders\UnitConverterDataConstants.h" />
<ClInclude Include="DataLoaders\UnitConverterDataLoader.h" /> <ClInclude Include="DataLoaders\UnitConverterDataLoader.h" />
<ClInclude Include="DateCalculatorViewModel.h" /> <ClInclude Include="DateCalculatorViewModel.h" />
@ -396,23 +395,6 @@
<Project>{fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}</Project> <Project>{fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemDefinitionGroup Condition="!Exists('DataLoaders\DataLoaderConstants.h')">
<ClCompile>
<AdditionalOptions>/DUSE_MOCK_DATA %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
</ItemDefinitionGroup>
<Choose>
<When Condition="Exists('DataLoaders\DataLoaderConstants.h')">
<ItemGroup>
<ClInclude Include="DataLoaders\DataLoaderConstants.h" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<ClInclude Include="DataLoaders\DataLoaderMockConstants.h" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup> <ItemGroup>
<None Include="DataLoaders\DefaultFromToCurrency.json" /> <None Include="DataLoaders\DefaultFromToCurrency.json" />
</ItemGroup> </ItemGroup>

View file

@ -171,12 +171,6 @@
<ClInclude Include="DataLoaders\CurrencyHttpClient.h"> <ClInclude Include="DataLoaders\CurrencyHttpClient.h">
<Filter>DataLoaders</Filter> <Filter>DataLoaders</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="DataLoaders\DataLoaderMockConstants.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="DataLoaders\ICurrencyHttpClient.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="DataLoaders\UnitConverterDataConstants.h"> <ClInclude Include="DataLoaders\UnitConverterDataConstants.h">
<Filter>DataLoaders</Filter> <Filter>DataLoaders</Filter>
</ClInclude> </ClInclude>

View file

@ -89,9 +89,8 @@ namespace CalculatorApp
} }
} }
CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr<ICurrencyHttpClient> client, const wchar_t* forcedResponseLanguage) CurrencyDataLoader::CurrencyDataLoader(const wchar_t* forcedResponseLanguage)
: m_client(move(client)) : m_loadStatus(CurrencyLoadStatus::NotLoaded)
, m_loadStatus(CurrencyLoadStatus::NotLoaded)
, m_responseLanguage(L"en-US") , m_responseLanguage(L"en-US")
, m_ratioFormat(L"") , m_ratioFormat(L"")
, m_timestampFormat(L"") , m_timestampFormat(L"")
@ -122,12 +121,7 @@ CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr<ICurrencyHttpClient> clie
} }
} }
if (m_client != nullptr) m_client.Initialize(StringReference{ DefaultCurrencyCode.data() }, m_responseLanguage);
{
m_client->SetSourceCurrencyCode(StringReference(DefaultCurrencyCode.data()));
m_client->SetResponseLanguage(m_responseLanguage);
}
auto localizationService = LocalizationService::GetInstance(); auto localizationService = LocalizationService::GetInstance();
if (CoreWindow::GetForCurrentThread() != nullptr) if (CoreWindow::GetForCurrentThread() != nullptr)
{ {
@ -199,7 +193,9 @@ void CurrencyDataLoader::LoadData()
if (!LoadFinished()) if (!LoadFinished())
{ {
RegisterForNetworkBehaviorChanges(); RegisterForNetworkBehaviorChanges();
create_task([this]() -> task<bool> { create_task(
[this]() -> task<bool>
{
vector<function<future<bool>()>> loadFunctions = { vector<function<future<bool>()>> loadFunctions = {
[this]() { return TryLoadDataFromCacheAsync(); }, [this]() { return TryLoadDataFromCacheAsync(); },
[this]() { return TryLoadDataFromWebAsync(); }, [this]() { return TryLoadDataFromWebAsync(); },
@ -218,7 +214,8 @@ void CurrencyDataLoader::LoadData()
co_return didLoad; co_return didLoad;
}) })
.then( .then(
[this](bool didLoad) { [this](bool didLoad)
{
UpdateDisplayedTimestamp(); UpdateDisplayedTimestamp();
NotifyDataLoadFinished(didLoad); NotifyDataLoadFinished(didLoad);
}, },
@ -283,9 +280,7 @@ double CurrencyDataLoader::RoundCurrencyRatio(double ratio)
int numberDecimals = FORMATTER_RATE_MIN_DECIMALS; int numberDecimals = FORMATTER_RATE_MIN_DECIMALS;
if (ratio < 1) if (ratio < 1)
{ {
numberDecimals = max( numberDecimals = max(FORMATTER_RATE_MIN_DECIMALS, (int)(-log10(ratio)) + FORMATTER_RATE_MIN_SIGNIFICANT_DECIMALS);
FORMATTER_RATE_MIN_DECIMALS,
(int)(-log10(ratio)) + FORMATTER_RATE_MIN_SIGNIFICANT_DECIMALS);
} }
unsigned long long scale = (unsigned long long)powl(10l, numberDecimals); unsigned long long scale = (unsigned long long)powl(10l, numberDecimals);
@ -314,8 +309,7 @@ pair<wstring, wstring> CurrencyDataLoader::GetCurrencyRatioEquality(_In_ const U
auto ratioString = LocalizationStringUtil::GetLocalizedString( auto ratioString = LocalizationStringUtil::GetLocalizedString(
m_ratioFormat, digitSymbol, StringReference(unit1.abbreviation.c_str()), roundedFormat, StringReference(unit2.abbreviation.c_str())); m_ratioFormat, digitSymbol, StringReference(unit1.abbreviation.c_str()), roundedFormat, StringReference(unit2.abbreviation.c_str()));
auto accessibleRatioString = auto accessibleRatioString = LocalizationStringUtil::GetLocalizedString(
LocalizationStringUtil::GetLocalizedString(
m_ratioFormat, digitSymbol, StringReference(unit1.accessibleName.c_str()), roundedFormat, StringReference(unit2.accessibleName.c_str())); m_ratioFormat, digitSymbol, StringReference(unit1.accessibleName.c_str()), roundedFormat, StringReference(unit2.accessibleName.c_str()));
return make_pair(ratioString->Data(), accessibleRatioString->Data()); return make_pair(ratioString->Data(), accessibleRatioString->Data());
@ -415,18 +409,14 @@ future<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
{ {
ResetLoadStatus(); ResetLoadStatus();
if (m_client == nullptr)
{
co_return false;
}
if (m_networkAccessBehavior == NetworkAccessBehavior::Offline || (m_networkAccessBehavior == NetworkAccessBehavior::OptIn && !m_meteredOverrideSet)) if (m_networkAccessBehavior == NetworkAccessBehavior::Offline || (m_networkAccessBehavior == NetworkAccessBehavior::OptIn && !m_meteredOverrideSet))
{ {
co_return false; co_return false;
} }
String ^ staticDataResponse = co_await m_client->GetCurrencyMetadata(); // TODO: determine if below getters are awaitables in production.
String ^ allRatiosResponse = co_await m_client->GetCurrencyRatios(); String ^ staticDataResponse = m_client.GetCurrencyMetadata();
String ^ allRatiosResponse = m_client.GetCurrencyRatios();
if (staticDataResponse == nullptr || allRatiosResponse == nullptr) if (staticDataResponse == nullptr || allRatiosResponse == nullptr)
{ {
co_return false; co_return false;
@ -550,9 +540,7 @@ bool CurrencyDataLoader::TryParseStaticData(_In_ String ^ rawJson, _Inout_ vecto
staticData[i] = CurrencyStaticData{ countryCode, countryName, currencyCode, currencyName, currencySymbol }; staticData[i] = CurrencyStaticData{ countryCode, countryName, currencyCode, currencyName, currencySymbol };
} }
auto sortCountryNames = [](const UCM::CurrencyStaticData & s) { auto sortCountryNames = [](const UCM::CurrencyStaticData& s) { return ref new String(s.countryName.c_str()); };
return ref new String(s.countryName.c_str());
};
LocalizationService::GetInstance()->Sort<UCM::CurrencyStaticData>(staticData, sortCountryNames); LocalizationService::GetInstance()->Sort<UCM::CurrencyStaticData>(staticData, sortCountryNames);

View file

@ -5,7 +5,7 @@
#include "CalcManager/UnitConverter.h" #include "CalcManager/UnitConverter.h"
#include "Common/NetworkManager.h" #include "Common/NetworkManager.h"
#include "ICurrencyHttpClient.h" #include "CurrencyHttpClient.h"
namespace CalculatorApp namespace CalculatorApp
{ {
@ -54,9 +54,7 @@ namespace CalculatorApp
class CurrencyDataLoader : public UCM::IConverterDataLoader, public UCM::ICurrencyConverterDataLoader class CurrencyDataLoader : public UCM::IConverterDataLoader, public UCM::ICurrencyConverterDataLoader
{ {
public: public:
CurrencyDataLoader( CurrencyDataLoader(const wchar_t* overrideLanguage = nullptr);
_In_ std::unique_ptr<CalculatorApp::ViewModel::DataLoaders::ICurrencyHttpClient> client,
const wchar_t* overrideLanguage = nullptr);
~CurrencyDataLoader(); ~CurrencyDataLoader();
bool LoadFinished(); bool LoadFinished();
@ -114,7 +112,7 @@ namespace CalculatorApp
private: private:
Platform::String ^ m_responseLanguage; Platform::String ^ m_responseLanguage;
std::unique_ptr<CalculatorApp::ViewModel::DataLoaders::ICurrencyHttpClient> m_client; CurrencyHttpClient m_client;
bool m_isRtlLanguage; bool m_isRtlLanguage;

View file

@ -4,47 +4,143 @@
#include "pch.h" #include "pch.h"
#include "CurrencyHttpClient.h" #include "CurrencyHttpClient.h"
#ifdef USE_MOCK_DATA namespace
#include "DataLoaderMockConstants.h"
#else
#include "DataLoaderConstants.h"
#endif
using namespace CalculatorApp::DataLoaders;
using namespace CalculatorApp::ViewModel::DataLoaders;
using namespace Platform;
using namespace std;
using namespace Windows::Foundation;
using namespace Windows::Web::Http;
CurrencyHttpClient::CurrencyHttpClient()
: m_client(ref new HttpClient())
, m_responseLanguage(L"en-US")
{ {
constexpr auto MockCurrencyConverterData = LR"(
[
{
"An": "MAR",
"Rt": 1.00
},
{
"An": "MON",
"Rt": 0.50
},
{
"An": "NEP",
"Rt": 0.00125
},
{
"An": "SAT",
"Rt": 0.25
},
{
"An": "URA",
"Rt": 2.75
},
{
"An": "VEN",
"Rt": 900.00
},
{
"An": "JUP",
"Rt": 1.23456789123456789
},
{
"An": "MER",
"Rt": 2.00
},
{
"An": "JPY",
"Rt": 0.00125
},
{
"An": "JOD",
"Rt": 0.25
} }
])";
constexpr auto MockCurrencyStaticData = LR"(
[
{
"CountryCode": "MAR",
"CountryName": "Mars",
"CurrencyCode": "MAR",
"CurrencyName": "The Martian Dollar",
"CurrencySymbol": "¤"
},
{
"CountryCode": "MON",
"CountryName": "Moon",
"CurrencyCode": "MON",
"CurrencyName": "Moon Bucks",
"CurrencySymbol": "¤"
},
{
"CountryCode": "NEP",
"CountryName": "Neptune",
"CurrencyCode": "NEP",
"CurrencyName": "Space Coins",
"CurrencySymbol": "¤"
},
{
"CountryCode": "SAT",
"CountryName": "Saturn",
"CurrencyCode": "SAT",
"CurrencyName": "Rings",
"CurrencySymbol": "¤"
},
{
"CountryCode": "URA",
"CountryName": "Uranus",
"CurrencyCode": "URA",
"CurrencyName": "Galaxy Credits",
"CurrencySymbol": "¤"
},
{
"CountryCode": "VEN",
"CountryName": "Venus",
"CurrencyCode": "VEN",
"CurrencyName": "Venusian Seashells",
"CurrencySymbol": "¤"
},
{
"CountryCode": "JUP",
"CountryName": "Jupiter",
"CurrencyCode": "JUP",
"CurrencyName": "Gas Money",
"CurrencySymbol": "¤"
},
{
"CountryCode": "MER",
"CountryName": "Mercury",
"CurrencyCode": "MER",
"CurrencyName": "Sun Notes",
"CurrencySymbol": "¤"
},
{
"CountryCode": "TEST1",
"CountryName": "Test No Fractional Digits",
"CurrencyCode": "JPY",
"CurrencyName": "Test No Fractional Digits",
"CurrencySymbol": "¤"
},
{
"CountryCode": "TEST2",
"CountryName": "Test Fractional Digits",
"CurrencyCode": "JOD",
"CurrencyName": "Test Fractional Digits",
"CurrencySymbol": "¤"
}
])";
} // namespace
void CurrencyHttpClient::SetSourceCurrencyCode(String ^ sourceCurrencyCode) namespace CalculatorApp::ViewModel::DataLoaders
{
void CurrencyHttpClient::Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage)
{ {
m_sourceCurrencyCode = sourceCurrencyCode; m_sourceCurrencyCode = sourceCurrencyCode;
}
void CurrencyHttpClient::SetResponseLanguage(String ^ responseLanguage)
{
m_responseLanguage = responseLanguage; m_responseLanguage = responseLanguage;
} }
IAsyncOperationWithProgress<String ^, HttpProgress> ^ CurrencyHttpClient::GetCurrencyMetadata() Platform::String ^ CurrencyHttpClient::GetCurrencyMetadata() const
{ {
wstring uri = wstring{ sc_MetadataUriLocalizeFor } + m_responseLanguage->Data(); (void)m_responseLanguage; // to be used in production.
auto metadataUri = ref new Uri(StringReference(uri.c_str())); return ref new Platform::String(MockCurrencyStaticData);
return m_client->GetStringAsync(metadataUri);
} }
IAsyncOperationWithProgress<String ^, HttpProgress> ^ CurrencyHttpClient::GetCurrencyRatios() Platform::String ^ CurrencyHttpClient::GetCurrencyRatios() const
{ {
wstring uri = wstring{ sc_RatiosUriRelativeTo } + m_sourceCurrencyCode->Data(); (void)m_sourceCurrencyCode; // to be used in production.
auto ratiosUri = ref new Uri(StringReference(uri.c_str())); return ref new Platform::String(MockCurrencyConverterData);
return m_client->GetStringAsync(ratiosUri);
} }
} // namespace CalculatorApp::ViewModel::DataLoaders

View file

@ -1,29 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. // Licensed under the MIT License.
#pragma once #pragma once
#include "ICurrencyHttpClient.h" namespace CalculatorApp::ViewModel::DataLoaders
namespace CalculatorApp
{ {
namespace ViewModel::DataLoaders class CurrencyHttpClient
{
class CurrencyHttpClient : public ICurrencyHttpClient
{ {
public: public:
CurrencyHttpClient(); void Initialize(Platform::String ^ sourceCurrencyCode, Platform::String ^ responseLanguage);
void SetSourceCurrencyCode(Platform::String ^ sourceCurrencyCode) override; Platform::String ^ GetCurrencyMetadata() const;
void SetResponseLanguage(Platform::String ^ responseLanguage) override; Platform::String ^ GetCurrencyRatios() const;
Windows::Foundation::IAsyncOperationWithProgress<Platform::String ^, Windows::Web::Http::HttpProgress> ^ GetCurrencyMetadata() override;
Windows::Foundation::IAsyncOperationWithProgress<Platform::String ^, Windows::Web::Http::HttpProgress> ^ GetCurrencyRatios() override;
private: private:
Windows::Web::Http::HttpClient ^ m_client;
Platform::String ^ m_responseLanguage;
Platform::String ^ m_sourceCurrencyCode; Platform::String ^ m_sourceCurrencyCode;
Platform::String ^ m_responseLanguage;
}; };
} }
}

View file

@ -1,13 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
namespace CalculatorApp
{
namespace DataLoaders
{
static constexpr auto sc_MetadataUriLocalizeFor = L"https://go.microsoft.com/fwlink/?linkid=2091028&localizeFor=";
static constexpr auto sc_RatiosUriRelativeTo = L"https://go.microsoft.com/fwlink/?linkid=2091307&localCurrency=";
}
}

View file

@ -1,24 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
namespace CalculatorApp
{
namespace ViewModel::DataLoaders
{
class ICurrencyHttpClient
{
public:
virtual ~ICurrencyHttpClient()
{
}
virtual void SetSourceCurrencyCode(Platform::String ^ sourceCurrencyCode) = 0;
virtual void SetResponseLanguage(Platform::String ^ responseLanguage) = 0;
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String ^, Windows::Web::Http::HttpProgress> ^ GetCurrencyMetadata() = 0;
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String ^, Windows::Web::Http::HttpProgress> ^ GetCurrencyRatios() = 0;
};
}
}

View file

@ -320,7 +320,6 @@
<ClInclude Include="..\CalcViewModel\Common\Utils.h" /> <ClInclude Include="..\CalcViewModel\Common\Utils.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyDataLoader.h" /> <ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyDataLoader.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyHttpClient.h" /> <ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyHttpClient.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\ICurrencyHttpClient.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataConstants.h" /> <ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataConstants.h" />
<ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataLoader.h" /> <ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataLoader.h" />
<ClInclude Include="..\CalcViewModel\DateCalculatorViewModel.h" /> <ClInclude Include="..\CalcViewModel\DateCalculatorViewModel.h" />
@ -391,31 +390,6 @@
<Project>{fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}</Project> <Project>{fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemDefinitionGroup Condition="!Exists('..\CalcViewModel\DataLoaders\DataLoaderConstants.h')">
<ClCompile>
<AdditionalOptions>/DUSE_MOCK_DATA %(AdditionalOptions)</AdditionalOptions>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">stdcpp17</LanguageStandard>
<LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Release|x64'">stdcpp17</LanguageStandard>
</ClCompile>
</ItemDefinitionGroup>
<Choose>
<When Condition="Exists('..\CalcViewModel\DataLoaders\DataLoaderConstants.h')">
<ItemGroup>
<ClInclude Include="..\CalcViewModel\DataLoaders\DataLoaderConstants.h" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<ClInclude Include="..\CalcViewModel\DataLoaders\DataLoaderMockConstants.h" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup> <ItemGroup>
<None Include="..\CalcViewModel\DataLoaders\DefaultFromToCurrency.json" /> <None Include="..\CalcViewModel\DataLoaders\DefaultFromToCurrency.json" />
</ItemGroup> </ItemGroup>

View file

@ -177,12 +177,6 @@
<ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyHttpClient.h"> <ClInclude Include="..\CalcViewModel\DataLoaders\CurrencyHttpClient.h">
<Filter>DataLoaders</Filter> <Filter>DataLoaders</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\CalcViewModel\DataLoaders\DataLoaderMockConstants.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="..\CalcViewModel\DataLoaders\ICurrencyHttpClient.h">
<Filter>DataLoaders</Filter>
</ClInclude>
<ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataConstants.h"> <ClInclude Include="..\CalcViewModel\DataLoaders\UnitConverterDataConstants.h">
<Filter>DataLoaders</Filter> <Filter>DataLoaders</Filter>
</ClInclude> </ClInclude>

View file

@ -1,15 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. // Licensed under the MIT License.
#pragma once #pragma once
#include "CalcViewModel/DataLoaders/ICurrencyHttpClient.h"
namespace CalculatorApp::ViewModel namespace CalculatorApp::ViewModel
{ {
namespace DataLoaders namespace DataLoaders
{ {
class CurrencyHttpClient : public ICurrencyHttpClient class CurrencyHttpClient
{ {
public: public:
CurrencyHttpClient(); CurrencyHttpClient();