mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 13:03:36 +00:00
@@ -102,14 +102,6 @@ std::string_view constexpr kTranslitMode = "TransliterationMode";
|
|||||||
std::string_view constexpr kPreferredGraphicsAPI = "PreferredGraphicsAPI";
|
std::string_view constexpr kPreferredGraphicsAPI = "PreferredGraphicsAPI";
|
||||||
std::string_view constexpr kShowDebugInfo = "DebugInfo";
|
std::string_view constexpr kShowDebugInfo = "DebugInfo";
|
||||||
std::string_view constexpr kScreenViewport = "ScreenClipRect";
|
std::string_view constexpr kScreenViewport = "ScreenClipRect";
|
||||||
std::string_view constexpr kPlacePageProductsPopupCloseTime = "PlacePageProductsPopupCloseTime";
|
|
||||||
std::string_view constexpr kPlacePageProductsPopupCloseReason = "PlacePageProductsPopupCloseReason";
|
|
||||||
std::string_view constexpr kPlacePageSelectedProduct = "PlacePageSelectedProduct";
|
|
||||||
|
|
||||||
std::string_view constexpr kProductsPopupCloseReasonCloseStr = "close";
|
|
||||||
std::string_view constexpr kProductsPopupCloseReasonRemindLaterStr = "remind_later";
|
|
||||||
std::string_view constexpr kProductsPopupCloseReasonAlreadyDonatedStr = "already_donated";
|
|
||||||
std::string_view constexpr kProductsPopupCloseReasonSelectProductStr = "select_product";
|
|
||||||
|
|
||||||
auto constexpr kLargeFontsScaleFactor = 1.6;
|
auto constexpr kLargeFontsScaleFactor = 1.6;
|
||||||
size_t constexpr kMaxTrafficCacheSizeBytes = 64 /* Mb */ * 1024 * 1024;
|
size_t constexpr kMaxTrafficCacheSizeBytes = 64 /* Mb */ * 1024 * 1024;
|
||||||
@@ -3281,104 +3273,3 @@ void Framework::OnPowerSchemeChanged(power_management::Scheme const actualScheme
|
|||||||
if (actualScheme == power_management::Scheme::EconomyMaximum && GetTrafficManager().IsEnabled())
|
if (actualScheme == power_management::Scheme::EconomyMaximum && GetTrafficManager().IsEnabled())
|
||||||
GetTrafficManager().SetEnabled(false);
|
GetTrafficManager().SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Framework::ShouldShowProducts() const
|
|
||||||
{
|
|
||||||
auto const connectionStatus = Platform::ConnectionStatus();
|
|
||||||
if (connectionStatus == Platform::EConnectionType::CONNECTION_NONE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::string donateUrl;
|
|
||||||
if (!settings::Get(settings::kDonateUrl, donateUrl)) // donation is disabled
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!m_usageStats.IsLoyalUser())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!HasPlacePageInfo()) // happens after the POI is deleted via the editor
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!storage::IsPointCoveredByDownloadedMaps(GetCurrentPlacePageInfo().GetMercator(), m_storage, *m_infoGetter))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint64_t popupCloseTime;
|
|
||||||
std::string productCloseReason;
|
|
||||||
if (!settings::Get(kPlacePageProductsPopupCloseTime, popupCloseTime) ||
|
|
||||||
!settings::Get(kPlacePageProductsPopupCloseReason, productCloseReason))
|
|
||||||
return true; // The popup was never closed.
|
|
||||||
|
|
||||||
auto const now = base::SecondsSinceEpoch();
|
|
||||||
auto const timeout = GetTimeoutForReason(FromString(productCloseReason));
|
|
||||||
bool const timeoutExpired = popupCloseTime + timeout < now;
|
|
||||||
if (timeoutExpired)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<products::ProductsConfig> Framework::GetProductsConfiguration() const
|
|
||||||
{
|
|
||||||
if (!ShouldShowProducts())
|
|
||||||
return nullopt;
|
|
||||||
return products::GetProductsConfiguration();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Framework::DidCloseProductsPopup(ProductsPopupCloseReason reason) const
|
|
||||||
{
|
|
||||||
settings::Set(kPlacePageProductsPopupCloseTime, base::SecondsSinceEpoch());
|
|
||||||
settings::Set(kPlacePageProductsPopupCloseReason, std::string(ToString(reason)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Framework::DidSelectProduct(products::ProductsConfig::Product const & product) const
|
|
||||||
{
|
|
||||||
settings::Set(kPlacePageSelectedProduct, product.GetTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Framework::GetTimeoutForReason(ProductsPopupCloseReason reason) const
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
uint32_t constexpr kPopupCloseTimeout = 10;
|
|
||||||
uint32_t constexpr kProductSelectTimeout = 20;
|
|
||||||
uint32_t constexpr kRemindMeLaterTimeout = 5;
|
|
||||||
#else
|
|
||||||
uint32_t constexpr kPopupCloseTimeout = 60 * 60 * 24 * 30; // 30 days
|
|
||||||
uint32_t constexpr kProductSelectTimeout = 60 * 60 * 24 * 180; // 180 days
|
|
||||||
uint32_t constexpr kRemindMeLaterTimeout = 60 * 60 * 24 * 3; // 3 days
|
|
||||||
#endif
|
|
||||||
switch (reason)
|
|
||||||
{
|
|
||||||
case ProductsPopupCloseReason::Close: return kPopupCloseTimeout;
|
|
||||||
case ProductsPopupCloseReason::RemindLater: return kRemindMeLaterTimeout;
|
|
||||||
case ProductsPopupCloseReason::AlreadyDonated: return kProductSelectTimeout;
|
|
||||||
case ProductsPopupCloseReason::SelectProduct: return kProductSelectTimeout;
|
|
||||||
}
|
|
||||||
ASSERT(false, ("Unknown reason"));
|
|
||||||
return kPopupCloseTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view Framework::ToString(ProductsPopupCloseReason reason) const
|
|
||||||
{
|
|
||||||
switch (reason)
|
|
||||||
{
|
|
||||||
case ProductsPopupCloseReason::Close: return kProductsPopupCloseReasonCloseStr;
|
|
||||||
case ProductsPopupCloseReason::RemindLater: return kProductsPopupCloseReasonRemindLaterStr;
|
|
||||||
case ProductsPopupCloseReason::AlreadyDonated: return kProductsPopupCloseReasonAlreadyDonatedStr;
|
|
||||||
case ProductsPopupCloseReason::SelectProduct: return kProductsPopupCloseReasonSelectProductStr;
|
|
||||||
}
|
|
||||||
ASSERT(false, ("Unknown reason"));
|
|
||||||
return kProductsPopupCloseReasonCloseStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Framework::ProductsPopupCloseReason Framework::FromString(std::string const & str) const
|
|
||||||
{
|
|
||||||
if (str == kProductsPopupCloseReasonCloseStr)
|
|
||||||
return ProductsPopupCloseReason::Close;
|
|
||||||
if (str == kProductsPopupCloseReasonRemindLaterStr)
|
|
||||||
return ProductsPopupCloseReason::RemindLater;
|
|
||||||
if (str == kProductsPopupCloseReasonAlreadyDonatedStr)
|
|
||||||
return ProductsPopupCloseReason::AlreadyDonated;
|
|
||||||
if (str == kProductsPopupCloseReasonSelectProductStr)
|
|
||||||
return ProductsPopupCloseReason::SelectProduct;
|
|
||||||
ASSERT(false, ("Incorrect reason string:", str));
|
|
||||||
return ProductsPopupCloseReason::Close;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
#include "platform/distance.hpp"
|
#include "platform/distance.hpp"
|
||||||
#include "platform/location.hpp"
|
#include "platform/location.hpp"
|
||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
#include "platform/products.hpp"
|
|
||||||
|
|
||||||
#include "routing/router.hpp"
|
#include "routing/router.hpp"
|
||||||
|
|
||||||
@@ -769,25 +768,4 @@ public:
|
|||||||
// PowerManager::Subscriber override.
|
// PowerManager::Subscriber override.
|
||||||
void OnPowerFacilityChanged(power_management::Facility const facility, bool enabled) override;
|
void OnPowerFacilityChanged(power_management::Facility const facility, bool enabled) override;
|
||||||
void OnPowerSchemeChanged(power_management::Scheme const actualScheme) override;
|
void OnPowerSchemeChanged(power_management::Scheme const actualScheme) override;
|
||||||
|
|
||||||
public:
|
|
||||||
bool ShouldShowProducts() const;
|
|
||||||
std::optional<products::ProductsConfig> GetProductsConfiguration() const;
|
|
||||||
|
|
||||||
enum class ProductsPopupCloseReason
|
|
||||||
{
|
|
||||||
Close,
|
|
||||||
SelectProduct,
|
|
||||||
AlreadyDonated,
|
|
||||||
RemindLater
|
|
||||||
};
|
|
||||||
|
|
||||||
ProductsPopupCloseReason FromString(std::string const & str) const;
|
|
||||||
|
|
||||||
void DidCloseProductsPopup(ProductsPopupCloseReason reason) const;
|
|
||||||
void DidSelectProduct(products::ProductsConfig::Product const & product) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t GetTimeoutForReason(ProductsPopupCloseReason reason) const;
|
|
||||||
std::string_view ToString(ProductsPopupCloseReason reason) const;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ set(SRC
|
|||||||
secure_storage.hpp
|
secure_storage.hpp
|
||||||
servers_list.cpp
|
servers_list.cpp
|
||||||
servers_list.hpp
|
servers_list.hpp
|
||||||
products.cpp
|
|
||||||
products.hpp
|
|
||||||
settings.cpp
|
settings.cpp
|
||||||
settings.hpp
|
settings.hpp
|
||||||
socket.hpp
|
socket.hpp
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ set(SRC
|
|||||||
measurement_tests.cpp
|
measurement_tests.cpp
|
||||||
platform_test.cpp
|
platform_test.cpp
|
||||||
meta_config_tests.cpp
|
meta_config_tests.cpp
|
||||||
products_tests.cpp
|
|
||||||
utm_mgrs_utils_tests.cpp
|
utm_mgrs_utils_tests.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "testing/testing.hpp"
|
#include "testing/testing.hpp"
|
||||||
|
|
||||||
#include "platform/products.hpp"
|
|
||||||
#include "platform/servers_list.hpp"
|
#include "platform/servers_list.hpp"
|
||||||
|
|
||||||
#include "cppjansson/cppjansson.hpp"
|
#include "cppjansson/cppjansson.hpp"
|
||||||
@@ -17,7 +16,6 @@ UNIT_TEST(MetaConfig_JSONParser_OldFormat)
|
|||||||
TEST_EQUAL(result->m_serversList[1], "http://url2", ());
|
TEST_EQUAL(result->m_serversList[1], "http://url2", ());
|
||||||
TEST_EQUAL(result->m_serversList[2], "http://url3", ());
|
TEST_EQUAL(result->m_serversList[2], "http://url3", ());
|
||||||
TEST(result->m_settings.empty(), ());
|
TEST(result->m_settings.empty(), ());
|
||||||
TEST(result->m_productsConfig.empty(), ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIT_TEST(MetaConfig_JSONParser_InvalidJSON)
|
UNIT_TEST(MetaConfig_JSONParser_InvalidJSON)
|
||||||
@@ -50,49 +48,6 @@ UNIT_TEST(MetaConfig_JSONParser_NewFormatWithoutProducts)
|
|||||||
TEST_EQUAL(result->m_serversList[1], "http://url2", ());
|
TEST_EQUAL(result->m_serversList[1], "http://url2", ());
|
||||||
TEST_EQUAL(result->m_settings.size(), 1, ());
|
TEST_EQUAL(result->m_settings.size(), 1, ());
|
||||||
TEST_EQUAL(result->m_settings["DonateUrl"], "value1", ());
|
TEST_EQUAL(result->m_settings["DonateUrl"], "value1", ());
|
||||||
TEST(result->m_productsConfig.empty(), ());
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIT_TEST(MetaConfig_JSONParser_NewFormatWithProducts)
|
|
||||||
{
|
|
||||||
std::string newFormatJson = R"({
|
|
||||||
"servers": ["http://url1", "http://url2"],
|
|
||||||
"settings": {
|
|
||||||
"DonateUrl": "value1",
|
|
||||||
"key2": "value2"
|
|
||||||
},
|
|
||||||
"productsConfig": {
|
|
||||||
"placePagePrompt": "prompt1",
|
|
||||||
"aboutScreenPrompt": "prompt2",
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"title": "Product 1",
|
|
||||||
"link": "http://product1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Product 2",
|
|
||||||
"link": "http://product2"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})";
|
|
||||||
|
|
||||||
auto result = ParseMetaConfig(newFormatJson);
|
|
||||||
TEST(result.has_value(), ());
|
|
||||||
TEST_EQUAL(result->m_serversList.size(), 2, ());
|
|
||||||
TEST_EQUAL(result->m_serversList[0], "http://url1", ());
|
|
||||||
TEST_EQUAL(result->m_serversList[1], "http://url2", ());
|
|
||||||
TEST_EQUAL(result->m_settings.size(), 1, ());
|
|
||||||
TEST_EQUAL(result->m_settings["DonateUrl"], "value1", ());
|
|
||||||
|
|
||||||
TEST(!result->m_productsConfig.empty(), ());
|
|
||||||
auto const productsConfigResult = products::ProductsConfig::Parse(result->m_productsConfig);
|
|
||||||
TEST(productsConfigResult.has_value(), ());
|
|
||||||
auto const productsConfig = productsConfigResult.value();
|
|
||||||
TEST_EQUAL(productsConfig.GetPlacePagePrompt(), "prompt1", ());
|
|
||||||
TEST(productsConfig.HasProducts(), ());
|
|
||||||
auto const products = productsConfig.GetProducts();
|
|
||||||
TEST_EQUAL(products.size(), 2, ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIT_TEST(MetaConfig_JSONParser_MissingServersKey)
|
UNIT_TEST(MetaConfig_JSONParser_MissingServersKey)
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
#include "testing/testing.hpp"
|
|
||||||
|
|
||||||
#include "platform/products.hpp"
|
|
||||||
|
|
||||||
#include "cppjansson/cppjansson.hpp"
|
|
||||||
|
|
||||||
using namespace products;
|
|
||||||
|
|
||||||
UNIT_TEST(ProductsConfig_ValidConfig)
|
|
||||||
{
|
|
||||||
std::string jsonStr = R"({
|
|
||||||
"placePagePrompt": "prompt1",
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"title": "Product 1",
|
|
||||||
"link": "http://product1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Product 2",
|
|
||||||
"link": "http://product2"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})";
|
|
||||||
|
|
||||||
auto const result = ProductsConfig::Parse(jsonStr);
|
|
||||||
TEST(result.has_value(), ());
|
|
||||||
auto const productsConfig = result.value();
|
|
||||||
TEST_EQUAL(productsConfig.GetPlacePagePrompt(), "prompt1", ());
|
|
||||||
|
|
||||||
auto const products = productsConfig.GetProducts();
|
|
||||||
TEST_EQUAL(products.size(), 2, ());
|
|
||||||
TEST_EQUAL(products[0].GetTitle(), "Product 1", ());
|
|
||||||
TEST_EQUAL(products[0].GetLink(), "http://product1", ());
|
|
||||||
TEST_EQUAL(products[1].GetTitle(), "Product 2", ());
|
|
||||||
TEST_EQUAL(products[1].GetLink(), "http://product2", ());
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIT_TEST(ProductsConfig_EmptyPrompts)
|
|
||||||
{
|
|
||||||
std::string jsonStr = R"({
|
|
||||||
"aboutScreenPrompt": "",
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"title": "Product 1",
|
|
||||||
"link": "http://product1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Product 2",
|
|
||||||
"link": "http://product2"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})";
|
|
||||||
|
|
||||||
auto const result = ProductsConfig::Parse(jsonStr);
|
|
||||||
TEST(result.has_value(), ());
|
|
||||||
auto const productsConfig = result.value();
|
|
||||||
TEST_EQUAL(productsConfig.GetPlacePagePrompt(), "", ());
|
|
||||||
TEST_EQUAL(productsConfig.GetProducts().size(), 2, ());
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIT_TEST(ProductsConfig_InvalidProduct)
|
|
||||||
{
|
|
||||||
std::string jsonStr = R"({
|
|
||||||
"placePagePrompt": "prompt1",
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"title": "Product 1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Product 2",
|
|
||||||
"link": "http://product2"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})";
|
|
||||||
|
|
||||||
auto const result = ProductsConfig::Parse(jsonStr);
|
|
||||||
TEST(result.has_value(), ());
|
|
||||||
auto const productsConfig = result.value();
|
|
||||||
TEST_EQUAL(productsConfig.GetPlacePagePrompt(), "prompt1", ());
|
|
||||||
|
|
||||||
auto const products = productsConfig.GetProducts();
|
|
||||||
TEST_EQUAL(products.size(), 1, ());
|
|
||||||
TEST_EQUAL(products[0].GetTitle(), "Product 2", ());
|
|
||||||
TEST_EQUAL(products[0].GetLink(), "http://product2", ());
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIT_TEST(ProductsConfig_EmptyProducts)
|
|
||||||
{
|
|
||||||
std::string jsonStr = R"({
|
|
||||||
"placePagePrompt": "prompt1",
|
|
||||||
"products": []
|
|
||||||
})";
|
|
||||||
|
|
||||||
auto const result = ProductsConfig::Parse(jsonStr);
|
|
||||||
TEST(!result.has_value(), ());
|
|
||||||
}
|
|
||||||
|
|
||||||
UNIT_TEST(ProductsConfig_MissedProductsField)
|
|
||||||
{
|
|
||||||
std::string jsonStr = R"({
|
|
||||||
"placePagePrompt": "prompt1"
|
|
||||||
})";
|
|
||||||
|
|
||||||
auto const result = ProductsConfig::Parse(jsonStr);
|
|
||||||
TEST(!result.has_value(), ());
|
|
||||||
}
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
#include "platform/products.hpp"
|
|
||||||
#include "platform/platform.hpp"
|
|
||||||
|
|
||||||
#include "base/assert.hpp"
|
|
||||||
#include "base/logging.hpp"
|
|
||||||
#include "base/string_utils.hpp"
|
|
||||||
|
|
||||||
#include "defines.hpp"
|
|
||||||
|
|
||||||
#include "coding/file_writer.hpp"
|
|
||||||
|
|
||||||
#include "cppjansson/cppjansson.hpp"
|
|
||||||
|
|
||||||
namespace products
|
|
||||||
{
|
|
||||||
|
|
||||||
char const kPlacePagePrompt[] = "placePagePrompt";
|
|
||||||
char const kProducts[] = "products";
|
|
||||||
char const kProductTitle[] = "title";
|
|
||||||
char const kProductLink[] = "link";
|
|
||||||
|
|
||||||
std::string GetProductsFilePath()
|
|
||||||
{
|
|
||||||
return GetPlatform().SettingsPathForFile(PRODUCTS_SETTINGS_FILE_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductsSettings::ProductsSettings()
|
|
||||||
{
|
|
||||||
std::lock_guard guard(m_mutex);
|
|
||||||
auto const path = GetProductsFilePath();
|
|
||||||
if (Platform::IsFileExistsByFullPath(path))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::string outValue;
|
|
||||||
auto dataReader = GetPlatform().GetReader(path);
|
|
||||||
dataReader->ReadAsString(outValue);
|
|
||||||
m_productsConfig = ProductsConfig::Parse(outValue);
|
|
||||||
}
|
|
||||||
catch (std::exception const & ex)
|
|
||||||
{
|
|
||||||
LOG(LERROR, ("Error reading ProductsConfig file.", ex.what()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG(LWARNING, ("ProductsConfig file not found."));
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductsSettings & ProductsSettings::Instance()
|
|
||||||
{
|
|
||||||
static ProductsSettings instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ProductsConfig> ProductsSettings::Get()
|
|
||||||
{
|
|
||||||
std::lock_guard guard(m_mutex);
|
|
||||||
return m_productsConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProductsSettings::Update(std::string const & jsonStr)
|
|
||||||
{
|
|
||||||
std::lock_guard guard(m_mutex);
|
|
||||||
if (jsonStr.empty())
|
|
||||||
FileWriter::DeleteFileX(GetProductsFilePath());
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
FileWriter file(GetProductsFilePath());
|
|
||||||
file.Write(jsonStr.data(), jsonStr.size());
|
|
||||||
m_productsConfig = ProductsConfig::Parse(jsonStr);
|
|
||||||
}
|
|
||||||
catch (std::exception const & ex)
|
|
||||||
{
|
|
||||||
LOG(LERROR, ("Error writing ProductsConfig file.", ex.what()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ProductsConfig> ProductsConfig::Parse(std::string const & jsonStr)
|
|
||||||
{
|
|
||||||
base::Json const root(jsonStr.c_str());
|
|
||||||
auto const json = root.get();
|
|
||||||
auto const productsObj = json_object_get(json, kProducts);
|
|
||||||
if (!json_is_object(json) || !productsObj || !json_is_array(productsObj))
|
|
||||||
{
|
|
||||||
LOG(LWARNING, ("Failed to parse ProductsConfig:", jsonStr));
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductsConfig config;
|
|
||||||
auto const placePagePrompt = json_object_get(json, kPlacePagePrompt);
|
|
||||||
if (placePagePrompt && json_is_string(placePagePrompt))
|
|
||||||
config.m_placePagePrompt = json_string_value(placePagePrompt);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < json_array_size(productsObj); ++i)
|
|
||||||
{
|
|
||||||
json_t * product = json_array_get(productsObj, i);
|
|
||||||
if (!product || !json_is_object(product))
|
|
||||||
{
|
|
||||||
LOG(LWARNING, ("Failed to parse Product:", jsonStr));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
json_t * title = json_object_get(product, kProductTitle);
|
|
||||||
json_t * link = json_object_get(product, kProductLink);
|
|
||||||
if (title && link && json_is_string(title) && json_is_string(link))
|
|
||||||
config.m_products.push_back({json_string_value(title), json_string_value(link)});
|
|
||||||
else
|
|
||||||
LOG(LWARNING, ("Failed to parse Product:", jsonStr));
|
|
||||||
}
|
|
||||||
if (config.m_products.empty())
|
|
||||||
{
|
|
||||||
LOG(LWARNING, ("Products list is empty"));
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace products
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace products
|
|
||||||
{
|
|
||||||
|
|
||||||
struct ProductsConfig
|
|
||||||
{
|
|
||||||
struct Product
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::string m_title;
|
|
||||||
std::string m_link;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Product(std::string const & title, std::string const & link) : m_title(title), m_link(link) {}
|
|
||||||
|
|
||||||
std::string const & GetTitle() const { return m_title; }
|
|
||||||
std::string const & GetLink() const { return m_link; }
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_placePagePrompt;
|
|
||||||
std::vector<Product> m_products;
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::string const GetPlacePagePrompt() const { return m_placePagePrompt; }
|
|
||||||
std::vector<Product> const & GetProducts() const { return m_products; }
|
|
||||||
bool HasProducts() const { return !m_products.empty(); }
|
|
||||||
|
|
||||||
static std::optional<ProductsConfig> Parse(std::string const & jsonStr);
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProductsSettings
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
ProductsSettings();
|
|
||||||
|
|
||||||
std::optional<ProductsConfig> m_productsConfig;
|
|
||||||
mutable std::mutex m_mutex;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static ProductsSettings & Instance();
|
|
||||||
|
|
||||||
void Update(std::string const & jsonStr);
|
|
||||||
std::optional<ProductsConfig> Get();
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void Update(std::string const & jsonStr)
|
|
||||||
{
|
|
||||||
ProductsSettings::Instance().Update(jsonStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::optional<ProductsConfig> GetProductsConfiguration()
|
|
||||||
{
|
|
||||||
return ProductsSettings::Instance().Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace products
|
|
||||||
@@ -16,7 +16,6 @@ std::optional<MetaConfig> ParseMetaConfig(std::string const & jsonStr)
|
|||||||
{
|
{
|
||||||
char const kSettings[] = "settings";
|
char const kSettings[] = "settings";
|
||||||
char const kServers[] = "servers";
|
char const kServers[] = "servers";
|
||||||
char const kProductsConfig[] = "productsConfig";
|
|
||||||
|
|
||||||
MetaConfig outMetaConfig;
|
MetaConfig outMetaConfig;
|
||||||
try
|
try
|
||||||
@@ -48,12 +47,6 @@ std::optional<MetaConfig> ParseMetaConfig(std::string const & jsonStr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
servers = json_object_get(root.get(), kServers);
|
servers = json_object_get(root.get(), kServers);
|
||||||
|
|
||||||
auto const productsConfig = json_object_get(root.get(), kProductsConfig);
|
|
||||||
if (productsConfig)
|
|
||||||
outMetaConfig.m_productsConfig = json_dumps(productsConfig, JSON_ENCODE_ANY);
|
|
||||||
else
|
|
||||||
LOG(LINFO, ("No ProductsConfig in meta configuration"));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ struct MetaConfig
|
|||||||
ServersList m_serversList;
|
ServersList m_serversList;
|
||||||
using SettingsMap = std::map<std::string, std::string>;
|
using SettingsMap = std::map<std::string, std::string>;
|
||||||
SettingsMap m_settings;
|
SettingsMap m_settings;
|
||||||
std::string m_productsConfig;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<MetaConfig> ParseMetaConfig(std::string const & jsonStr);
|
std::optional<MetaConfig> ParseMetaConfig(std::string const & jsonStr);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include "platform/http_client.hpp"
|
#include "platform/http_client.hpp"
|
||||||
#include "platform/locale.hpp"
|
#include "platform/locale.hpp"
|
||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
#include "platform/products.hpp"
|
|
||||||
#include "platform/servers_list.hpp"
|
#include "platform/servers_list.hpp"
|
||||||
#include "platform/settings.hpp"
|
#include "platform/settings.hpp"
|
||||||
|
|
||||||
@@ -48,7 +47,6 @@ void MapFilesDownloader::RunMetaConfigAsync(std::function<void()> && callback)
|
|||||||
{
|
{
|
||||||
m_serversList = metaConfig.m_serversList;
|
m_serversList = metaConfig.m_serversList;
|
||||||
settings::Update(metaConfig.m_settings);
|
settings::Update(metaConfig.m_settings);
|
||||||
products::Update(metaConfig.m_productsConfig);
|
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
// Reset flag to invoke servers list downloading next time if current request has failed.
|
// Reset flag to invoke servers list downloading next time if current request has failed.
|
||||||
|
|||||||
@@ -111,10 +111,7 @@
|
|||||||
D5B191CF2386C7E4009CD0D6 /* http_uploader_background.hpp in Headers */ = {isa = PBXBuildFile; fileRef = D5B191CE2386C7E4009CD0D6 /* http_uploader_background.hpp */; };
|
D5B191CF2386C7E4009CD0D6 /* http_uploader_background.hpp in Headers */ = {isa = PBXBuildFile; fileRef = D5B191CE2386C7E4009CD0D6 /* http_uploader_background.hpp */; };
|
||||||
EB60B4DC204C130300E4953B /* network_policy_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = EB60B4DB204C130300E4953B /* network_policy_ios.mm */; };
|
EB60B4DC204C130300E4953B /* network_policy_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = EB60B4DB204C130300E4953B /* network_policy_ios.mm */; };
|
||||||
EB60B4DE204C175700E4953B /* network_policy_ios.h in Headers */ = {isa = PBXBuildFile; fileRef = EB60B4DD204C175700E4953B /* network_policy_ios.h */; };
|
EB60B4DE204C175700E4953B /* network_policy_ios.h in Headers */ = {isa = PBXBuildFile; fileRef = EB60B4DD204C175700E4953B /* network_policy_ios.h */; };
|
||||||
ED49D7402CEE438E004AF27E /* products.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED49D73F2CEE438E004AF27E /* products.cpp */; };
|
|
||||||
ED49D7412CEE438E004AF27E /* products.hpp in Headers */ = {isa = PBXBuildFile; fileRef = ED49D73E2CEE438E004AF27E /* products.hpp */; };
|
|
||||||
ED49D7442CEE43A4004AF27E /* meta_config_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED49D7422CEE43A4004AF27E /* meta_config_tests.cpp */; };
|
ED49D7442CEE43A4004AF27E /* meta_config_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED49D7422CEE43A4004AF27E /* meta_config_tests.cpp */; };
|
||||||
ED49D7452CEE43A4004AF27E /* products_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED49D7432CEE43A4004AF27E /* products_tests.cpp */; };
|
|
||||||
ED965B252CD8F72E0049E39E /* duration.hpp in Headers */ = {isa = PBXBuildFile; fileRef = ED965B242CD8F72A0049E39E /* duration.hpp */; };
|
ED965B252CD8F72E0049E39E /* duration.hpp in Headers */ = {isa = PBXBuildFile; fileRef = ED965B242CD8F72A0049E39E /* duration.hpp */; };
|
||||||
ED965B272CD8F7810049E39E /* duration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED965B262CD8F77D0049E39E /* duration.cpp */; };
|
ED965B272CD8F7810049E39E /* duration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED965B262CD8F77D0049E39E /* duration.cpp */; };
|
||||||
ED965B472CDA52DB0049E39E /* duration_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED965B462CDA4EC00049E39E /* duration_tests.cpp */; };
|
ED965B472CDA52DB0049E39E /* duration_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ED965B462CDA4EC00049E39E /* duration_tests.cpp */; };
|
||||||
@@ -257,10 +254,7 @@
|
|||||||
D5B191CE2386C7E4009CD0D6 /* http_uploader_background.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = http_uploader_background.hpp; sourceTree = "<group>"; };
|
D5B191CE2386C7E4009CD0D6 /* http_uploader_background.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = http_uploader_background.hpp; sourceTree = "<group>"; };
|
||||||
EB60B4DB204C130300E4953B /* network_policy_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = network_policy_ios.mm; sourceTree = "<group>"; };
|
EB60B4DB204C130300E4953B /* network_policy_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = network_policy_ios.mm; sourceTree = "<group>"; };
|
||||||
EB60B4DD204C175700E4953B /* network_policy_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = network_policy_ios.h; sourceTree = "<group>"; };
|
EB60B4DD204C175700E4953B /* network_policy_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = network_policy_ios.h; sourceTree = "<group>"; };
|
||||||
ED49D73E2CEE438E004AF27E /* products.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = products.hpp; sourceTree = "<group>"; };
|
|
||||||
ED49D73F2CEE438E004AF27E /* products.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = products.cpp; sourceTree = "<group>"; };
|
|
||||||
ED49D7422CEE43A4004AF27E /* meta_config_tests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = meta_config_tests.cpp; sourceTree = "<group>"; };
|
ED49D7422CEE43A4004AF27E /* meta_config_tests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = meta_config_tests.cpp; sourceTree = "<group>"; };
|
||||||
ED49D7432CEE43A4004AF27E /* products_tests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = products_tests.cpp; sourceTree = "<group>"; };
|
|
||||||
ED965B242CD8F72A0049E39E /* duration.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = duration.hpp; sourceTree = "<group>"; };
|
ED965B242CD8F72A0049E39E /* duration.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = duration.hpp; sourceTree = "<group>"; };
|
||||||
ED965B262CD8F77D0049E39E /* duration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = duration.cpp; sourceTree = "<group>"; };
|
ED965B262CD8F77D0049E39E /* duration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = duration.cpp; sourceTree = "<group>"; };
|
||||||
ED965B462CDA4EC00049E39E /* duration_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = duration_tests.cpp; sourceTree = "<group>"; };
|
ED965B462CDA4EC00049E39E /* duration_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = duration_tests.cpp; sourceTree = "<group>"; };
|
||||||
@@ -323,7 +317,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
ED49D7422CEE43A4004AF27E /* meta_config_tests.cpp */,
|
ED49D7422CEE43A4004AF27E /* meta_config_tests.cpp */,
|
||||||
ED49D7432CEE43A4004AF27E /* products_tests.cpp */,
|
|
||||||
ED965B462CDA4EC00049E39E /* duration_tests.cpp */,
|
ED965B462CDA4EC00049E39E /* duration_tests.cpp */,
|
||||||
168EFCC12A30EB7400F71EE8 /* distance_tests.cpp */,
|
168EFCC12A30EB7400F71EE8 /* distance_tests.cpp */,
|
||||||
675341001C58C4C9002CF0D9 /* apk_test.cpp */,
|
675341001C58C4C9002CF0D9 /* apk_test.cpp */,
|
||||||
@@ -465,8 +458,6 @@
|
|||||||
6753439E1A3F5D5A00A0A8C3 /* platform_unix_impl.cpp */,
|
6753439E1A3F5D5A00A0A8C3 /* platform_unix_impl.cpp */,
|
||||||
675343A41A3F5D5A00A0A8C3 /* preferred_languages.hpp */,
|
675343A41A3F5D5A00A0A8C3 /* preferred_languages.hpp */,
|
||||||
675343A31A3F5D5A00A0A8C3 /* preferred_languages.cpp */,
|
675343A31A3F5D5A00A0A8C3 /* preferred_languages.cpp */,
|
||||||
ED49D73E2CEE438E004AF27E /* products.hpp */,
|
|
||||||
ED49D73F2CEE438E004AF27E /* products.cpp */,
|
|
||||||
4564FA7C2094978C0043CCFB /* remote_file.hpp */,
|
4564FA7C2094978C0043CCFB /* remote_file.hpp */,
|
||||||
4564FA7D2094978D0043CCFB /* remote_file.cpp */,
|
4564FA7D2094978D0043CCFB /* remote_file.cpp */,
|
||||||
3D78157C1F3D8A0A0068B6AC /* safe_callback.hpp */,
|
3D78157C1F3D8A0A0068B6AC /* safe_callback.hpp */,
|
||||||
@@ -554,7 +545,6 @@
|
|||||||
675343CD1A3F5D5A00A0A8C3 /* platform.hpp in Headers */,
|
675343CD1A3F5D5A00A0A8C3 /* platform.hpp in Headers */,
|
||||||
6741250F1B4C00CC00A3E828 /* local_country_file.hpp in Headers */,
|
6741250F1B4C00CC00A3E828 /* local_country_file.hpp in Headers */,
|
||||||
3D15ACE2214A707900F725D5 /* localization.hpp in Headers */,
|
3D15ACE2214A707900F725D5 /* localization.hpp in Headers */,
|
||||||
ED49D7412CEE438E004AF27E /* products.hpp in Headers */,
|
|
||||||
D5B191CF2386C7E4009CD0D6 /* http_uploader_background.hpp in Headers */,
|
D5B191CF2386C7E4009CD0D6 /* http_uploader_background.hpp in Headers */,
|
||||||
1669C8422A30DCD200530AD1 /* distance.hpp in Headers */,
|
1669C8422A30DCD200530AD1 /* distance.hpp in Headers */,
|
||||||
3DE8B98F1DEC3115000E6083 /* network_policy.hpp in Headers */,
|
3DE8B98F1DEC3115000E6083 /* network_policy.hpp in Headers */,
|
||||||
@@ -710,7 +700,6 @@
|
|||||||
ED965B272CD8F7810049E39E /* duration.cpp in Sources */,
|
ED965B272CD8F7810049E39E /* duration.cpp in Sources */,
|
||||||
EB60B4DC204C130300E4953B /* network_policy_ios.mm in Sources */,
|
EB60B4DC204C130300E4953B /* network_policy_ios.mm in Sources */,
|
||||||
6741250E1B4C00CC00A3E828 /* local_country_file.cpp in Sources */,
|
6741250E1B4C00CC00A3E828 /* local_country_file.cpp in Sources */,
|
||||||
ED49D7402CEE438E004AF27E /* products.cpp in Sources */,
|
|
||||||
670E8C761BB318AB00094197 /* platform_ios.mm in Sources */,
|
670E8C761BB318AB00094197 /* platform_ios.mm in Sources */,
|
||||||
67A2526A1BB40E100063F8A8 /* platform_qt.cpp in Sources */,
|
67A2526A1BB40E100063F8A8 /* platform_qt.cpp in Sources */,
|
||||||
56EB1EDE1C6B6E6C0022D831 /* mwm_traits.cpp in Sources */,
|
56EB1EDE1C6B6E6C0022D831 /* mwm_traits.cpp in Sources */,
|
||||||
@@ -748,7 +737,6 @@
|
|||||||
files = (
|
files = (
|
||||||
6783389E1C6DE59200FD6263 /* platform_test.cpp in Sources */,
|
6783389E1C6DE59200FD6263 /* platform_test.cpp in Sources */,
|
||||||
ED49D7442CEE43A4004AF27E /* meta_config_tests.cpp in Sources */,
|
ED49D7442CEE43A4004AF27E /* meta_config_tests.cpp in Sources */,
|
||||||
ED49D7452CEE43A4004AF27E /* products_tests.cpp in Sources */,
|
|
||||||
678338961C6DE59200FD6263 /* apk_test.cpp in Sources */,
|
678338961C6DE59200FD6263 /* apk_test.cpp in Sources */,
|
||||||
678338991C6DE59200FD6263 /* jansson_test.cpp in Sources */,
|
678338991C6DE59200FD6263 /* jansson_test.cpp in Sources */,
|
||||||
ED965B482CDA575B0049E39E /* duration.cpp in Sources */,
|
ED965B482CDA575B0049E39E /* duration.cpp in Sources */,
|
||||||
|
|||||||
Reference in New Issue
Block a user