diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index 486e5da2ec..ae51822ecf 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -26,6 +26,8 @@ #include "std/target_os.hpp" +#include "3party/Alohalytics/src/alohalytics.h" + #include #include @@ -140,6 +142,8 @@ BookmarkManager::BookmarkManager(Callbacks && callbacks) , m_changesTracker(*this) , m_needTeardown(false) , m_nextGroupID(UserMark::BOOKMARK) + , m_bookmarkCloud(Cloud::CloudParams("bmc.json", "bookmarks", "BookmarkCloudParam", + std::string(KMZ_EXTENSION))) { ASSERT(m_callbacks.m_getStringsBundle != nullptr, ()); m_userMarkLayers.reserve(UserMark::BOOKMARK); @@ -148,6 +152,23 @@ BookmarkManager::BookmarkManager(Callbacks && callbacks) m_selectionMark = CreateUserMark(m2::PointD{}); m_myPositionMark = CreateUserMark(m2::PointD{}); + + m_bookmarkCloud.SetSynchronizationHandlers([]() + { + alohalytics::Stats::Instance().LogEvent("Bookmarks_sync_started"); + }, [](Cloud::SynchronizationResult result, std::string const & errorStr) + { + if (result == Cloud::SynchronizationResult::Success) + { + alohalytics::Stats::Instance().LogEvent("Bookmarks_sync_success"); + } + else + { + std::string const typeStr = (result == Cloud::SynchronizationResult::DiskError) ? "disk" : "network"; + alohalytics::TStringMap details {{"type", typeStr}, {"error", errorStr}}; + alohalytics::Stats::Instance().LogEvent("Bookmarks_sync_error", details); + } + }); } BookmarkManager::~BookmarkManager() @@ -510,16 +531,24 @@ void BookmarkManager::LoadBookmarks() auto collection = std::make_shared(); collection->reserve(files.size()); + std::vector filePaths; + filePaths.reserve(files.size()); for (auto const & file : files) { - auto kmlData = LoadKMLFile(dir + file); + auto const filePath = dir + file; + auto kmlData = LoadKMLFile(filePath); if (m_needTeardown) return; if (kmlData != nullptr) + { + filePaths.push_back(filePath); collection->emplace_back(std::move(kmlData)); + } } NotifyAboutFinishAsyncLoading(std::move(collection)); + GetPlatform().RunTask(Platform::Thread::Gui, + [this, filePaths]() { m_bookmarkCloud.Init(filePaths); }); }); LoadState(); @@ -563,6 +592,12 @@ void BookmarkManager::LoadBookmarkRoutine(std::string const & filePath, bool isT NotifyAboutFile(dataExists, filePath, isTemporaryFile); } NotifyAboutFinishAsyncLoading(std::move(collection)); + + if (fileSavePath) + { + GetPlatform().RunTask(Platform::Thread::Gui, + [this, fileSavePath]() { m_bookmarkCloud.Init({fileSavePath.get()}); }); + } }); } @@ -590,6 +625,8 @@ void BookmarkManager::NotifyAboutFinishAsyncLoading(std::shared_ptrempty()) CreateCategories(std::move(*collection)); + else + CheckAndCreateDefaultCategory(); if (m_asyncLoadingCallbacks.m_onFinished != nullptr) m_asyncLoadingCallbacks.m_onFinished(); @@ -694,10 +731,7 @@ df::MarkGroupID BookmarkManager::LastEditedBMCategory() if (cat.second->GetFileName() == m_lastCategoryUrl) return cat.first; } - - if (m_categories.empty()) - CreateBookmarkCategory(m_callbacks.m_getStringsBundle().GetString("my_places")); - + CheckAndCreateDefaultCategory(); return m_bmGroupsIdList.front(); } @@ -768,6 +802,12 @@ df::MarkGroupID BookmarkManager::CreateBookmarkCategory(std::string const & name return groupId; } +void BookmarkManager::CheckAndCreateDefaultCategory() +{ + if (m_categories.empty()) + CreateBookmarkCategory(m_callbacks.m_getStringsBundle().GetString("my_places")); +} + bool BookmarkManager::DeleteBmCategory(df::MarkGroupID groupID) { auto it = m_categories.find(groupID); @@ -1160,6 +1200,31 @@ bool BookmarkManager::SaveToKMLFile(df::MarkGroupID groupID) return false; } +void BookmarkManager::SetCloudEnabled(bool enabled) +{ + m_bookmarkCloud.SetState(enabled ? Cloud::State::Enabled : Cloud::State::Disabled); +} + +bool BookmarkManager::IsCloudEnabled() const +{ + return m_bookmarkCloud.GetState() == Cloud::State::Enabled; +} + +uint64_t BookmarkManager::GetLastSynchronizationTimestamp() const +{ + return m_bookmarkCloud.GetLastSynchronizationTimestamp(); +} + +std::unique_ptr BookmarkManager::GetUserSubscriber() +{ + return m_bookmarkCloud.GetUserSubscriber(); +} + +void BookmarkManager::SetInvalidTokenHandler(Cloud::InvalidTokenHandler && onInvalidToken) +{ + m_bookmarkCloud.SetInvalidTokenHandler(std::move(onInvalidToken)); +} + df::GroupIDSet BookmarkManager::MarksChangesTracker::GetAllGroupIds() const { auto const & groupIds = m_bmManager.GetBmGroupsIdList(); diff --git a/map/bookmark_manager.hpp b/map/bookmark_manager.hpp index d4bb0ef515..960dad6447 100644 --- a/map/bookmark_manager.hpp +++ b/map/bookmark_manager.hpp @@ -1,6 +1,7 @@ #pragma once #include "map/bookmark.hpp" +#include "map/cloud.hpp" #include "map/user_mark_layer.hpp" #include "drape_frontend/drape_engine_safe_ptr.hpp" @@ -185,6 +186,12 @@ public: MyPositionMarkPoint & MyPositionMark() { return *m_myPositionMark; } MyPositionMarkPoint const & MyPositionMark() const { return *m_myPositionMark; } + void SetCloudEnabled(bool enabled); + bool IsCloudEnabled() const; + uint64_t GetLastSynchronizationTimestamp() const; + std::unique_ptr GetUserSubscriber(); + void SetInvalidTokenHandler(Cloud::InvalidTokenHandler && onInvalidToken); + private: class MarksChangesTracker : public df::UserMarksProvider { @@ -312,6 +319,7 @@ private: void SendBookmarksChanges(); void GetBookmarksData(df::MarkIDSet const & markIds, std::vector> & data) const; + void CheckAndCreateDefaultCategory(); Callbacks m_callbacks; MarksChangesTracker m_changesTracker; @@ -351,5 +359,7 @@ private: }; std::list m_bookmarkLoadingQueue; + Cloud m_bookmarkCloud; + DISALLOW_COPY_AND_MOVE(BookmarkManager); }; diff --git a/map/cloud.cpp b/map/cloud.cpp index 939f6e08d5..f36a8f3477 100644 --- a/map/cloud.cpp +++ b/map/cloud.cpp @@ -77,6 +77,7 @@ Cloud::Cloud(CloudParams && params) } m_state = static_cast(stateValue); + GetPlatform().RunTask(Platform::Thread::File, [this]() { ReadIndex(); }); } Cloud::~Cloud() @@ -153,6 +154,15 @@ void Cloud::MarkModified(std::string const & filePath) MarkModifiedImpl(filePath, false /* checkSize */); } +uint64_t Cloud::GetLastSynchronizationTimestamp() const +{ + std::lock_guard lock(m_mutex); + if (m_state != State::Enabled) + return 0; + + return m_index.m_lastSyncTimestamp * 1000; // in milliseconds. +} + std::unique_ptr Cloud::GetUserSubscriber() { auto s = std::make_unique(); @@ -166,17 +176,17 @@ std::unique_ptr Cloud::GetUserSubscriber() void Cloud::LoadIndex() { - auto const indexFilePath = GetIndexFilePath(m_params.m_indexName); - if (GetPlatform().IsFileExistsByFullPath(indexFilePath)) - ReadIndex(indexFilePath); - + ReadIndex(); UpdateIndex(); - ScheduleUploading(); } -void Cloud::ReadIndex(std::string const & indexFilePath) +void Cloud::ReadIndex() { + auto const indexFilePath = GetIndexFilePath(m_params.m_indexName); + if (!GetPlatform().IsFileExistsByFullPath(indexFilePath)) + return; + // Read index file. std::string data; try @@ -276,7 +286,7 @@ Cloud::EntryPtr Cloud::GetEntryImpl(std::string const & filePath) const void Cloud::SaveIndexImpl() const { - if (m_state != State::Enabled) + if (m_state != State::Enabled || m_index.m_entries.empty()) return; std::string jsonData; diff --git a/map/cloud.hpp b/map/cloud.hpp index def9aa7f02..f65db9319b 100644 --- a/map/cloud.hpp +++ b/map/cloud.hpp @@ -53,7 +53,7 @@ public: std::vector m_entries; uint64_t m_lastUpdateInHours = 0; bool m_isOutdated = false; - uint64_t m_lastSyncTimestamp = 0; + uint64_t m_lastSyncTimestamp = 0; // in seconds. DECLARE_VISITOR_AND_DEBUG_PRINT(Index, visitor(m_entries, "entries"), visitor(m_lastUpdateInHours, "lastUpdateInHours"), @@ -156,7 +156,7 @@ public: std::string m_zipExtension; }; - Cloud(CloudParams && params); + explicit Cloud(CloudParams && params); ~Cloud(); void SetInvalidTokenHandler(InvalidTokenHandler && onInvalidToken); @@ -165,6 +165,8 @@ public: void SetState(State state); State GetState() const; + // Return timestamp of the last synchronization in milliseconds. + uint64_t GetLastSynchronizationTimestamp() const; void Init(std::vector const & filePaths); void MarkModified(std::string const & filePath); @@ -173,7 +175,7 @@ public: private: void LoadIndex(); - void ReadIndex(std::string const & indexFilePath); + void ReadIndex(); void UpdateIndex(); void SaveIndexImpl() const; diff --git a/map/framework.cpp b/map/framework.cpp index b90ac27885..447ceb2489 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1,7 +1,6 @@ #include "map/framework.hpp" #include "map/benchmark_tools.hpp" #include "map/chart_generator.hpp" -#include "map/cloud.hpp" #include "map/displayed_categories_modifiers.hpp" #include "map/everywhere_search_params.hpp" #include "map/ge0_parser.hpp" @@ -439,26 +438,8 @@ Framework::Framework(FrameworkParams const & params) m_routingManager.SetBookmarkManager(m_bmManager.get()); m_searchMarks.SetBookmarkManager(m_bmManager.get()); - //TODO: move into refactored BookmarkManager - m_bookmarkCloud = make_unique(Cloud::CloudParams("bmc.json", "bookmarks", "BookmarkCloudParam", ".kmz")); - m_bookmarkCloud->SetInvalidTokenHandler([this] { m_user.ResetAccessToken(); }); - m_bookmarkCloud->SetSynchronizationHandlers([]() - { - alohalytics::Stats::Instance().LogEvent("Bookmarks_sync_started"); - }, [](Cloud::SynchronizationResult result, std::string const & errorStr) - { - if (result == Cloud::SynchronizationResult::Success) - { - alohalytics::Stats::Instance().LogEvent("Bookmarks_sync_success"); - } - else - { - std::string const typeStr = (result == Cloud::SynchronizationResult::DiskError) ? "disk" : "network"; - alohalytics::TStringMap details {{"type", typeStr}, {"error", errorStr}}; - alohalytics::Stats::Instance().LogEvent("Bookmarks_sync_error", details); - } - }); - m_user.AddSubscriber(m_bookmarkCloud->GetUserSubscriber()); + m_bmManager->SetInvalidTokenHandler([this] { m_user.ResetAccessToken(); }); + m_user.AddSubscriber(m_bmManager->GetUserSubscriber()); InitCityFinder(); InitDiscoveryManager(); @@ -524,8 +505,7 @@ Framework::~Framework() DestroyDrapeEngine(); m_model.SetOnMapDeregisteredCallback(nullptr); - //TODO: move into refactored BookmarkManager - m_bookmarkCloud->SetInvalidTokenHandler(nullptr); + m_bmManager->SetInvalidTokenHandler(nullptr); m_user.ClearSubscribers(); } diff --git a/map/framework.hpp b/map/framework.hpp index 9379295875..17d6f4223a 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -107,8 +107,6 @@ namespace ads class Engine; } -class Cloud; - /// Uncomment line to make fixed position settings and /// build version for screenshots. //#define FIXED_LOCATION @@ -190,8 +188,6 @@ protected: location::TMyPositionModeChanged m_myPositionListener; unique_ptr m_bmManager; - //TODO: move into refactored BookmarkManager - unique_ptr m_bookmarkCloud; SearchMarks m_searchMarks; diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt index 36f2c43d57..faeead578a 100644 --- a/qt/CMakeLists.txt +++ b/qt/CMakeLists.txt @@ -8,6 +8,7 @@ QT5_ADD_RESOURCES(RES_SOURCES res/resources.qrc) include_directories( ${OMIM_ROOT}/3party/glm ${OMIM_ROOT}/3party/gflags/src + ${OMIM_ROOT}/3party/jansson/src ) set( diff --git a/qt/qt_common/CMakeLists.txt b/qt/qt_common/CMakeLists.txt index 3786734096..0aaa80d174 100644 --- a/qt/qt_common/CMakeLists.txt +++ b/qt/qt_common/CMakeLists.txt @@ -2,6 +2,10 @@ project(qt_common) QT5_ADD_RESOURCES(RESOURCES res/resources_common.qrc) +include_directories( + ${OMIM_ROOT}/3party/jansson/src +) + set( SRC helpers.cpp