forked from organicmaps/organicmaps
Persistent bookmark ids.
This commit is contained in:
parent
3bdc883d65
commit
e6d910a9eb
10 changed files with 174 additions and 31 deletions
|
@ -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>>;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
extension MWMBookmarksManager {
|
||||
@nonobjc static func groupsIdList() -> [MWMMarkGroupID] {
|
||||
return groupsIdList().map { $0.uint32Value }
|
||||
return groupsIdList().map { $0.uint64Value }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(); }
|
||||
|
|
Loading…
Add table
Reference in a new issue