Persistent bookmark ids.

This commit is contained in:
Daria Volvenkova 2018-04-02 17:30:56 +03:00 committed by Roman Kuznetsov
parent 3bdc883d65
commit e6d910a9eb
10 changed files with 174 additions and 31 deletions

View file

@ -6,9 +6,9 @@
namespace df
{
using MarkID = uint32_t;
using LineID = uint32_t;
using MarkGroupID = uint32_t;
using MarkID = uint64_t;
using LineID = uint64_t;
using MarkGroupID = uint64_t;
using MarkIDCollection = std::vector<MarkID>;
using LineIDCollection = std::vector<LineID>;
using MarkIDSet = std::set<MarkID, std::greater<MarkID>>;

View file

@ -15,9 +15,9 @@ typedef NS_ENUM(NSUInteger, MWMTheme) {
MWMThemeAuto
};
typedef uint32_t MWMMarkID;
typedef uint32_t MWMLineID;
typedef uint32_t MWMMarkGroupID;
typedef uint64_t MWMMarkID;
typedef uint64_t MWMLineID;
typedef uint64_t MWMMarkGroupID;
typedef NSArray<NSNumber *> * MWMGroupIDCollection;
typedef NS_ENUM(NSUInteger, MWMBookmarksShareStatus) {

View file

@ -1,5 +1,5 @@
extension MWMBookmarksManager {
@nonobjc static func groupsIdList() -> [MWMMarkGroupID] {
return groupsIdList().map { $0.uint32Value }
return groupsIdList().map { $0.uint64Value }
}
}

View file

@ -35,13 +35,16 @@ Bookmark::Bookmark(m2::PointD const & ptOrg)
, m_groupId(df::kInvalidMarkGroupId)
{
m_data.m_point = ptOrg;
m_data.m_id = GetId();
}
Bookmark::Bookmark(kml::BookmarkData const & data)
: Base(data.m_point, UserMark::BOOKMARK)
: Base(data.m_id, data.m_point, UserMark::BOOKMARK)
, m_data(data)
, m_groupId(df::kInvalidMarkGroupId)
{}
{
m_data.m_id = GetId();
}
void Bookmark::SetData(kml::BookmarkData const & data)
{
@ -181,6 +184,7 @@ BookmarkCategory::BookmarkCategory(std::string const & name, df::MarkGroupID gro
, m_groupId(groupId)
, m_autoSave(autoSave)
{
m_data.m_id = groupId;
SetName(name);
}
@ -190,6 +194,7 @@ BookmarkCategory::BookmarkCategory(kml::CategoryData const & data, df::MarkGroup
, m_autoSave(autoSave)
, m_data(data)
{
m_data.m_id = groupId;
Base::SetIsVisible(m_data.m_visible);
}

View file

@ -43,12 +43,34 @@ using namespace std::placeholders;
namespace
{
std::string const kLastBookmarkCategoryId = "LastBookmarkCategoryId";
std::string const kLastBookmarkCategory = "LastBookmarkCategory";
std::string const kLastBookmarkType = "LastBookmarkType";
std::string const kLastBookmarkColor = "LastBookmarkColor";
std::string const kKmzExtension = ".kmz";
std::string const kBookmarksExt = ".kmb";
uint64_t LoadLastBmCategoryId()
{
uint64_t lastId;
std::string val;
if (GetPlatform().GetSecureStorage().Load(kLastBookmarkCategoryId, val) && strings::to_uint64(val, lastId))
return lastId;
return static_cast<uint64_t>(UserMark::BOOKMARK);
}
void SaveLastBmCategoryId(uint64_t lastId)
{
GetPlatform().GetSecureStorage().Save(kLastBookmarkCategoryId, strings::to_string(lastId));
}
uint64_t ResetLastBmCategoryId()
{
auto const lastId = static_cast<uint64_t>(UserMark::BOOKMARK);
SaveLastBmCategoryId(lastId);
return lastId;
}
// Returns extension with a dot in a lower case.
std::string GetFileExt(std::string const & filePath)
{
@ -402,13 +424,14 @@ BookmarkManager::BookmarkManager(Callbacks && callbacks)
: m_callbacks(std::move(callbacks))
, m_changesTracker(*this)
, m_needTeardown(false)
, m_nextGroupID(UserMark::BOOKMARK)
, m_lastGroupID(LoadLastBmCategoryId())
, m_bookmarkCloud(Cloud::CloudParams("bmc.json", "bookmarks", "BookmarkCloudParam",
GetBookmarksDirectory(), std::string(kBookmarksExt),
std::bind(&ConvertBeforeUploading, _1, _2),
std::bind(&ConvertAfterDownloading, _1, _2)))
{
ASSERT(m_callbacks.m_getStringsBundle != nullptr, ());
ASSERT_GREATER_OR_EQUAL(m_lastGroupID, UserMark::BOOKMARK, ());
m_userMarkLayers.reserve(UserMark::BOOKMARK);
for (uint32_t i = 0; i < UserMark::BOOKMARK; ++i)
m_userMarkLayers.emplace_back(std::make_unique<UserMarkLayer>(static_cast<UserMark::Type>(i)));
@ -1026,9 +1049,14 @@ void BookmarkManager::NotifyAboutFinishAsyncLoading(std::shared_ptr<KMLDataColle
m_asyncLoadingInProgress = false;
m_loadBookmarksFinished = true;
if (!collection->empty())
{
CreateCategories(std::move(*collection));
}
else
{
CheckAndResetLastIds();
CheckAndCreateDefaultCategory();
}
if (m_asyncLoadingCallbacks.m_onFinished != nullptr)
m_asyncLoadingCallbacks.m_onFinished();
@ -1136,15 +1164,15 @@ df::MarkGroupID BookmarkManager::LastEditedBMCategory()
{
ASSERT_THREAD_CHECKER(m_threadChecker, ());
if (HasBmCategory(m_lastGroupId))
return m_lastGroupId;
if (HasBmCategory(m_lastEditedGroupId))
return m_lastEditedGroupId;
for (auto & cat : m_categories)
{
if (cat.second->GetFileName() == m_lastCategoryUrl)
{
m_lastGroupId = cat.first;
return m_lastGroupId;
m_lastEditedGroupId = cat.first;
return m_lastEditedGroupId;
}
}
CheckAndCreateDefaultCategory();
@ -1159,7 +1187,7 @@ kml::PredefinedColor BookmarkManager::LastEditedBMColor() const
void BookmarkManager::SetLastEditedBmCategory(df::MarkGroupID groupId)
{
m_lastGroupId = groupId;
m_lastEditedGroupId = groupId;
m_lastCategoryUrl = GetBmCategory(groupId)->GetFileName();
SaveState();
}
@ -1237,7 +1265,13 @@ bool BookmarkManager::HasBmCategory(df::MarkGroupID groupId) const
df::MarkGroupID BookmarkManager::CreateBookmarkCategory(kml::CategoryData const & data, bool autoSave)
{
ASSERT_THREAD_CHECKER(m_threadChecker, ());
auto const groupId = m_nextGroupID++;
auto groupId = data.m_id;
if (groupId == kml::kInvalidCategoryId)
{
groupId = ++m_lastGroupID;
SaveLastBmCategoryId(m_lastGroupID);
}
ASSERT_EQUAL(m_categories.count(groupId), 0, ());
auto & cat = m_categories[groupId];
cat = my::make_unique<BookmarkCategory>(data, groupId, autoSave);
m_bmGroupsIdList.push_back(groupId);
@ -1248,7 +1282,8 @@ df::MarkGroupID BookmarkManager::CreateBookmarkCategory(kml::CategoryData const
df::MarkGroupID BookmarkManager::CreateBookmarkCategory(std::string const & name, bool autoSave)
{
ASSERT_THREAD_CHECKER(m_threadChecker, ());
auto const groupId = m_nextGroupID++;
auto const groupId = ++m_lastGroupID;
SaveLastBmCategoryId(m_lastGroupID);
auto & cat = m_categories[groupId];
cat = my::make_unique<BookmarkCategory>(name, groupId, autoSave);
m_bmGroupsIdList.push_back(groupId);
@ -1263,6 +1298,16 @@ void BookmarkManager::CheckAndCreateDefaultCategory()
CreateBookmarkCategory(m_callbacks.m_getStringsBundle().GetString("core_my_places"));
}
void BookmarkManager::CheckAndResetLastIds()
{
if (m_categories.empty())
m_lastGroupID = ResetLastBmCategoryId();
if (m_bookmarks.empty())
UserMark::ResetLastId(UserMark::BOOKMARK);
if (m_tracks.empty())
Track::ResetLastId();
}
bool BookmarkManager::DeleteBmCategory(df::MarkGroupID groupId)
{
ASSERT_THREAD_CHECKER(m_threadChecker, ());
@ -1385,7 +1430,8 @@ void BookmarkManager::CreateCategories(KMLDataCollection && dataCollection, bool
}
else
{
groupId = CreateBookmarkCategory(categoryData, false /* autoSave */);
bool const saveAfterCreation = categoryData.m_id == df::kInvalidMarkGroupId;
groupId = CreateBookmarkCategory(categoryData, saveAfterCreation);
loadedGroups.insert(groupId);
group = GetBmCategory(groupId);
group->SetFileName(fileName);

View file

@ -415,6 +415,7 @@ private:
void GetBookmarksData(df::MarkIDSet const & markIds,
std::vector<std::pair<df::MarkID, kml::BookmarkData>> & data) const;
void CheckAndCreateDefaultCategory();
void CheckAndResetLastIds();
std::unique_ptr<kml::FileData> CollectBmGroupKMLData(BookmarkCategory const * group) const;
void SaveToFile(kml::FileData & kmlData, Writer & writer, bool useBinary) const;
@ -434,7 +435,7 @@ private:
df::DrapeEngineSafePtr m_drapeEngine;
AsyncLoadingCallbacks m_asyncLoadingCallbacks;
std::atomic<bool> m_needTeardown;
df::MarkGroupID m_nextGroupID;
df::MarkGroupID m_lastGroupID;
size_t m_openedEditSessionsCount = 0;
bool m_loadBookmarksFinished = false;
bool m_firstDrapeNotification = false;
@ -445,7 +446,7 @@ private:
df::GroupIDCollection m_bmGroupsIdList;
std::string m_lastCategoryUrl;
df::MarkGroupID m_lastGroupId = df::kInvalidMarkGroupId;
df::MarkGroupID m_lastEditedGroupId = df::kInvalidMarkGroupId;
kml::PredefinedColor m_lastColor = kml::PredefinedColor::Red;
UserMarkLayers m_userMarkLayers;

View file

@ -6,25 +6,62 @@
#include "geometry/distance_on_sphere.hpp"
#include "platform/platform.hpp"
#include "base/string_utils.hpp"
namespace
{
df::LineID GetNextUserLineId()
static const std::string kLastLineId = "LastLineId";
uint64_t LoadLastLineId()
{
static std::atomic<uint32_t> nextLineId(0);
return static_cast<df::LineID>(++nextLineId);
uint64_t lastId;
std::string val;
if (GetPlatform().GetSecureStorage().Load(kLastLineId, val) && strings::to_uint64(val, lastId))
return lastId;
return 0;
}
void SaveLastLineId(uint64_t lastId)
{
GetPlatform().GetSecureStorage().Save(kLastLineId, strings::to_string(lastId));
}
df::LineID GetNextUserLineId(bool reset = false)
{
static std::atomic<uint64_t> lastLineId(LoadLastLineId());
if (reset)
{
SaveLastLineId(0);
lastLineId = 0;
return df::kInvalidLineId;
}
auto const id = static_cast<df::LineID>(++lastLineId);
SaveLastLineId(lastLineId);
return id;
}
} // namespace
Track::Track(kml::TrackData const & data)
: df::UserLineMark(GetNextUserLineId())
: df::UserLineMark(data.m_id == df::kInvalidLineId ? GetNextUserLineId() : data.m_id)
, m_data(data)
, m_groupID(0)
{
m_data.m_id = GetId();
ASSERT_GREATER(m_data.m_points.size(), 1, ());
}
string const & Track::GetName() const
// static
void Track::ResetLastId()
{
UNUSED_VALUE(GetNextUserLineId(true /* reset */));
}
string Track::GetName() const
{
return kml::GetDefaultStr(m_data.m_name);
}

View file

@ -22,13 +22,14 @@ class Track : public df::UserLineMark
public:
explicit Track(kml::TrackData const & data);
static void ResetLastId();
bool IsDirty() const override { return m_isDirty; }
void ResetChanges() const override { m_isDirty = false; }
kml::TrackData const & GetData() const { return m_data; }
//void SetData(kml::TrackData const & data) { m_data = data; }
string const & GetName() const;
std::string GetName() const;
m2::RectD GetLimitRect() const;
double GetLengthMeters() const;

View file

@ -5,6 +5,8 @@
#include "geometry/mercator.hpp"
#include "platform/platform.hpp"
#include "base/string_utils.hpp"
#include <atomic>
@ -12,17 +14,60 @@
namespace
{
static const uint32_t kMarkIdTypeBitsCount = 4;
static const std::string kLastBookmarkId = "LastBookmarkId";
df::MarkID GetNextUserMarkId(UserMark::Type type)
uint64_t LoadLastBookmarkId()
{
static std::atomic<uint32_t> nextMarkId(0);
uint64_t lastId;
std::string val;
if (GetPlatform().GetSecureStorage().Load(kLastBookmarkId, val) && strings::to_uint64(val, lastId))
return lastId;
return 0;
}
void SaveLastBookmarkId(uint64_t lastId)
{
GetPlatform().GetSecureStorage().Save(kLastBookmarkId, strings::to_string(lastId));
}
df::MarkID GetNextUserMarkId(UserMark::Type type, bool reset = false)
{
static std::atomic<uint64_t> lastBookmarkId(LoadLastBookmarkId());
static std::atomic<uint64_t> lastUserMarkId(0);
if (reset)
{
if (type == UserMark::Type::BOOKMARK)
{
SaveLastBookmarkId(0);
lastBookmarkId = 0;
}
return df::kInvalidMarkId;
}
static_assert(UserMark::Type::BOOKMARK < (1 << kMarkIdTypeBitsCount), "Not enough bits for user mark type.");
return static_cast<df::MarkID>(
(++nextMarkId) | (type << static_cast<uint32_t>(sizeof(df::MarkID) * 8 - kMarkIdTypeBitsCount)));
auto const typeBits = static_cast<uint64_t>(type) << (sizeof(df::MarkID) * 8 - kMarkIdTypeBitsCount);
if (type == UserMark::Type::BOOKMARK)
{
auto const id = static_cast<df::MarkID>((++lastBookmarkId) | typeBits);
SaveLastBookmarkId(lastBookmarkId);
return id;
}
else
{
return static_cast<df::MarkID>((++lastUserMarkId) | typeBits);
}
}
} // namespace
UserMark::UserMark(df::MarkID id, m2::PointD const & ptOrg, UserMark::Type type)
: df::UserPointMark(id == df::kInvalidMarkId ? GetNextUserMarkId(type) : id)
, m_ptOrg(ptOrg)
{
ASSERT_EQUAL(GetMarkType(), type, ());
}
UserMark::UserMark(m2::PointD const & ptOrg, UserMark::Type type)
: df::UserPointMark(GetNextUserMarkId(type))
, m_ptOrg(ptOrg)
@ -34,6 +79,12 @@ UserMark::Type UserMark::GetMarkType(df::MarkID id)
return static_cast<Type>(id >> (sizeof(id) * 8 - kMarkIdTypeBitsCount));
}
// static
void UserMark::ResetLastId(UserMark::Type type)
{
UNUSED_VALUE(GetNextUserMarkId(type, true /* reset */));
}
m2::PointD const & UserMark::GetPivot() const
{
return m_ptOrg;

View file

@ -42,9 +42,11 @@ public:
BOOKMARK, // Should always be the last one
};
UserMark(df::MarkID id, m2::PointD const & ptOrg, UserMark::Type type);
UserMark(m2::PointD const & ptOrg, UserMark::Type type);
static Type GetMarkType(df::MarkID id);
static void ResetLastId(UserMark::Type type);
Type GetMarkType() const { return GetMarkType(GetId()); }
df::MarkGroupID GetGroupId() const override { return GetMarkType(); }