Refactored bookmark sharing as async process

This commit is contained in:
Roman Kuznetsov 2018-03-24 14:54:21 +03:00 committed by Vlad Mihaylenko
parent f7d14c8925
commit fe7b5bddca
8 changed files with 126 additions and 111 deletions

View file

@ -67,7 +67,7 @@ final class BMCViewController: MWMViewController {
let fileName = (url.lastPathComponent as NSString).deletingPathExtension
let message = String(coreFormat: L("share_bookmarks_email_body"), arguments: [fileName])
let shareController = AVC.share(for: url, message: message) { [viewModel] _, _, _, _ in
viewModel?.endShareCategory(category: category)
viewModel?.finishShareCategory()
}
shareController!.present(inParentViewController: self, anchorView: anchor)
}
@ -75,11 +75,12 @@ final class BMCViewController: MWMViewController {
let showAlertOnError = { (title: String, text: String) in
MWMAlertViewController.activeAlert().presentInfoAlert(title, text: text)
}
let shareCategoryStatus = viewModel.beginShareCategory(category: category)
switch shareCategoryStatus {
case let .success(url): shareOnSuccess(url)
case let .error(title, text): showAlertOnError(title, text)
viewModel.shareCategory(category: category) { (status: BMCShareCategoryStatus) in
switch status {
case let .success(url): shareOnSuccess(url)
case let .error(title, text): showAlertOnError(title, text)
}
}
}

View file

@ -14,6 +14,8 @@ final class BMCDefaultViewModel: NSObject {
private(set) var isPendingPermission = false
private var isAuthenticated = false
private var onPreparedToShareCategory: BMCViewModel.onPreparedToShareHandler?
var minCategoryNameLength: UInt = Const.minCategoryNameLength
var maxCategoryNameLength: UInt = Const.maxCategoryNameLength
@ -159,20 +161,14 @@ extension BMCDefaultViewModel: BMCViewModel {
return BM.checkCategoryName(name)
}
func beginShareCategory(category: BMCCategory) -> BMCShareCategoryStatus {
switch BM.beginShareCategory(category.identifier) {
case .success:
return .success(BM.shareCategoryURL())
case .emptyCategory:
return .error(title: L("bookmarks_error_title_share_empty"), text: L("bookmarks_error_message_share_empty"))
case .archiveError: fallthrough
case .fileError:
return .error(title: L("dialog_routing_system_error"), text: L("bookmarks_error_message_share_general"))
}
func shareCategory(category: BMCCategory, handler: @escaping onPreparedToShareHandler) {
onPreparedToShareCategory = handler
BM.shareCategory(category.identifier)
}
func endShareCategory(category: BMCCategory) {
BM.endShareCategory(category.identifier)
func finishShareCategory() {
BM.finishShareCategory()
onPreparedToShareCategory = nil
}
func pendingPermission(isPending: Bool) {
@ -209,4 +205,16 @@ extension BMCDefaultViewModel: MWMBookmarksObserver {
func onBookmarkDeleted(_: MWMMarkID) {
loadData()
}
func onBookmarksCategoryFilePrepared(_ status: MWMBookmarksShareStatus) {
switch status {
case .success:
onPreparedToShareCategory?(.success(BM.shareCategoryURL()))
case .emptyCategory:
onPreparedToShareCategory?(.error(title: L("bookmarks_error_title_share_empty"), text: L("bookmarks_error_message_share_empty")))
case .archiveError: fallthrough
case .fileError:
onPreparedToShareCategory?(.error(title: L("dialog_routing_system_error"), text: L("bookmarks_error_message_share_general")))
}
}
}

View file

@ -32,8 +32,9 @@ protocol BMCViewModel: AnyObject {
func deleteCategory(category: BMCCategory)
func checkCategory(name: String) -> Bool
func beginShareCategory(category: BMCCategory) -> BMCShareCategoryStatus
func endShareCategory(category: BMCCategory)
typealias onPreparedToShareHandler = (BMCShareCategoryStatus) -> Void
func shareCategory(category: BMCCategory, handler: @escaping onPreparedToShareHandler)
func finishShareCategory()
func pendingPermission(isPending: Bool)
func grant(permission: BMCPermission?)

View file

@ -24,9 +24,9 @@
+ (void)deleteBookmark:(MWMMarkID)bookmarkId;
+ (BOOL)checkCategoryName:(NSString *)name;
+ (MWMBookmarksShareStatus)beginShareCategory:(MWMMarkGroupID)groupId;
+ (void)shareCategory:(MWMMarkGroupID)groupId;
+ (NSURL *)shareCategoryURL;
+ (void)endShareCategory:(MWMMarkGroupID)groupId;
+ (void)finishShareCategory;
+ (NSDate *)lastSynchronizationDate;
+ (BOOL)isCloudEnabled;

View file

@ -4,6 +4,8 @@
#include "Framework.h"
#include "coding/internal/file_data.hpp"
namespace
{
using Observer = id<MWMBookmarksObserver>;
@ -188,25 +190,38 @@ using TLoopBlock = void (^)(Observer observer);
return !GetFramework().GetBookmarkManager().IsUsedCategoryName(name.UTF8String);
}
+ (MWMBookmarksShareStatus)beginShareCategory:(MWMMarkGroupID)groupId
+ (void)shareCategory:(MWMMarkGroupID)groupId
{
auto const sharingResult = GetFramework().GetBookmarkManager().BeginSharing(groupId);
switch (sharingResult.m_code)
{
case BookmarkManager::SharingResult::Code::Success:
GetFramework().GetBookmarkManager().PrepareFileForSharing(groupId, [](auto sharingResult)
{
MWMBookmarksShareStatus status;
MWMBookmarksManager * manager = [MWMBookmarksManager manager];
manager.shareCategoryURL =
[NSURL fileURLWithPath:@(sharingResult.m_sharingPath.c_str()) isDirectory:NO];
NSAssert(manager.shareCategoryURL != nil, @"Invalid share category url");
return MWMBookmarksShareStatusSuccess;
}
case BookmarkManager::SharingResult::Code::EmptyCategory:
return MWMBookmarksShareStatusEmptyCategory;
case BookmarkManager::SharingResult::Code::ArchiveError:
return MWMBookmarksShareStatusArchiveError;
case BookmarkManager::SharingResult::Code::FileError: return MWMBookmarksShareStatusFileError;
}
switch (sharingResult.m_code)
{
case BookmarkManager::SharingResult::Code::Success:
{
manager.shareCategoryURL = [NSURL fileURLWithPath:@(sharingResult.m_sharingPath.c_str())
isDirectory:NO];
NSAssert(manager.shareCategoryURL != nil, @"Invalid share category url");
status = MWMBookmarksShareStatusSuccess;
break;
}
case BookmarkManager::SharingResult::Code::EmptyCategory:
status = MWMBookmarksShareStatusEmptyCategory;
break;
case BookmarkManager::SharingResult::Code::ArchiveError:
status = MWMBookmarksShareStatusArchiveError;
break;
case BookmarkManager::SharingResult::Code::FileError:
status = MWMBookmarksShareStatusFileError;
break;
}
[manager loopObservers:^(Observer observer) {
if ([observer respondsToSelector:@selector(onBookmarksCategoryFilePrepared:)])
[observer onBookmarksCategoryFilePrepared:status];
}];
});
}
+ (NSURL *)shareCategoryURL
@ -216,11 +231,14 @@ using TLoopBlock = void (^)(Observer observer);
return manager.shareCategoryURL;
}
+ (void)endShareCategory:(MWMMarkGroupID)groupId
+ (void)finishShareCategory
{
MWMBookmarksManager * manager = [MWMBookmarksManager manager];
if (!manager.shareCategoryURL)
return;
my::DeleteFileX(manager.shareCategoryURL.path.UTF8String);
manager.shareCategoryURL = nil;
GetFramework().GetBookmarkManager().EndSharing(groupId);
}
+ (NSDate *)lastSynchronizationDate

View file

@ -7,5 +7,6 @@
- (void)onBookmarksFileLoadSuccess;
- (void)onBookmarksCategoryDeleted:(MWMMarkGroupID)groupId;
- (void)onBookmarkDeleted:(MWMMarkID)bookmarkId;
- (void)onBookmarksCategoryFilePrepared:(MWMBookmarksShareStatus)status;
@end

View file

@ -110,6 +110,38 @@ public:
m2::AnyRectD const & m_rect;
m2::PointD m_globalCenter;
};
BookmarkManager::SharingResult GetFileForSharing(df::MarkGroupID categoryId, std::string const & filePath)
{
if (!GetPlatform().IsFileExistsByFullPath(filePath))
{
return BookmarkManager::SharingResult(categoryId, BookmarkManager::SharingResult::Code::FileError,
"Bookmarks file does not exist.");
}
auto ext = my::GetFileExtension(filePath);
strings::AsciiToLower(ext);
std::string fileName = filePath;
my::GetNameFromFullPath(fileName);
my::GetNameWithoutExt(fileName);
auto const tmpFilePath = my::JoinFoldersToPath(GetPlatform().TmpDir(), fileName + KMZ_EXTENSION);
if (ext == KMZ_EXTENSION)
{
if (my::CopyFileX(filePath, tmpFilePath))
return BookmarkManager::SharingResult(categoryId, tmpFilePath);
return BookmarkManager::SharingResult(categoryId, BookmarkManager::SharingResult::Code::FileError,
"Could not copy file.");
}
if (!CreateZipFromPathDeflatedAndDefaultCompression(filePath, tmpFilePath))
{
return BookmarkManager::SharingResult(categoryId, BookmarkManager::SharingResult::Code::ArchiveError,
"Could not create archive.");
}
return BookmarkManager::SharingResult(categoryId, tmpFilePath);
}
} // namespace
namespace migration
@ -1457,37 +1489,21 @@ void BookmarkManager::SetInvalidTokenHandler(Cloud::InvalidTokenHandler && onInv
m_bookmarkCloud.SetInvalidTokenHandler(std::move(onInvalidToken));
}
BookmarkManager::SharingResult BookmarkManager::BeginSharing(df::MarkGroupID categoryId)
void BookmarkManager::PrepareFileForSharing(df::MarkGroupID categoryId, SharingHandler && handler)
{
auto const it = m_activeSharing.find(categoryId);
if (it != m_activeSharing.end())
ASSERT_THREAD_CHECKER(m_threadChecker, ());
ASSERT(handler, ());
if (IsCategoryEmpty(categoryId))
{
// In case if the sharing has already begun.
if (GetPlatform().IsFileExistsByFullPath(it->second))
return SharingResult(it->second);
}
auto const result = GetFileForSharing(categoryId);
if (result.m_code != SharingResult::Code::Success)
{
m_activeSharing.erase(categoryId);
return result;
}
m_activeSharing[categoryId] = result.m_sharingPath;
return result;
}
void BookmarkManager::EndSharing(df::MarkGroupID categoryId)
{
auto const it = m_activeSharing.find(categoryId);
if (it == m_activeSharing.end())
handler(SharingResult(categoryId, SharingResult::Code::EmptyCategory));
return;
}
if (GetPlatform().IsFileExistsByFullPath(it->second))
my::DeleteFileX(it->second);
m_activeSharing.erase(categoryId);
auto const filePath = GetCategoryFileName(categoryId);
GetPlatform().RunTask(Platform::Thread::File, [categoryId, filePath, handler = std::move(handler)]()
{
handler(GetFileForSharing(categoryId, filePath));
});
}
bool BookmarkManager::IsCategoryEmpty(df::MarkGroupID categoryId) const
@ -1536,36 +1552,6 @@ void BookmarkManager::SetAllCategoriesVisibility(bool visible)
c.second->SetIsVisible(visible);
}
BookmarkManager::SharingResult BookmarkManager::GetFileForSharing(df::MarkGroupID categoryId)
{
ASSERT_THREAD_CHECKER(m_threadChecker, ());
if (IsCategoryEmpty(categoryId))
return SharingResult(SharingResult::Code::EmptyCategory);
auto const filePath = GetCategoryFileName(categoryId);
if (!GetPlatform().IsFileExistsByFullPath(filePath))
return SharingResult(SharingResult::Code::FileError, "Bookmarks file does not exist.");
auto ext = my::GetFileExtension(filePath);
strings::AsciiToLower(ext);
std::string fileName = filePath;
my::GetNameFromFullPath(fileName);
my::GetNameWithoutExt(fileName);
auto const tmpFilePath = my::JoinFoldersToPath(GetPlatform().TmpDir(), fileName + KMZ_EXTENSION);
if (ext == KMZ_EXTENSION)
{
if (my::CopyFileX(filePath, tmpFilePath))
return SharingResult(tmpFilePath);
return SharingResult(SharingResult::Code::FileError, "Could not copy file.");
}
if (!CreateZipFromPathDeflatedAndDefaultCompression(filePath, tmpFilePath))
return SharingResult(SharingResult::Code::ArchiveError, "Could not create archive.");
return SharingResult(tmpFilePath);
}
size_t BookmarkManager::GetKmlFilesCountForConversion() const
{
// The conversion available only after successful migration.

View file

@ -204,27 +204,31 @@ public:
ArchiveError,
FileError
};
df::MarkGroupID m_categoryId;
Code m_code;
std::string m_sharingPath;
std::string m_errorString;
explicit SharingResult(std::string const & sharingPath)
: m_code(Code::Success)
SharingResult(df::MarkGroupID categoryId, std::string const & sharingPath)
: m_categoryId(categoryId)
, m_code(Code::Success)
, m_sharingPath(sharingPath)
{}
explicit SharingResult(Code code)
: m_code(code)
SharingResult(df::MarkGroupID categoryId, Code code)
: m_categoryId(categoryId)
, m_code(code)
{}
SharingResult(Code code, std::string const & errorString)
: m_code(code)
SharingResult(df::MarkGroupID categoryId, Code code, std::string const & errorString)
: m_categoryId(categoryId)
, m_code(code)
, m_errorString(errorString)
{}
};
SharingResult BeginSharing(df::MarkGroupID categoryId);
void EndSharing(df::MarkGroupID categoryId);
using SharingHandler = platform::SafeCallback<void(SharingResult const & result)>;
void PrepareFileForSharing(df::MarkGroupID categoryId, SharingHandler && handler);
bool IsCategoryEmpty(df::MarkGroupID categoryId) const;
@ -251,7 +255,7 @@ private:
class MarksChangesTracker : public df::UserMarksProvider
{
public:
MarksChangesTracker(BookmarkManager & bmManager) : m_bmManager(bmManager) {}
explicit MarksChangesTracker(BookmarkManager & bmManager) : m_bmManager(bmManager) {}
void OnAddMark(df::MarkID markId);
void OnDeleteMark(df::MarkID markId);
@ -393,8 +397,6 @@ private:
void SaveToKML(BookmarkCategory * group, std::ostream & s);
SharingResult GetFileForSharing(df::MarkGroupID categoryId);
ThreadChecker m_threadChecker;
Callbacks m_callbacks;
@ -428,7 +430,7 @@ private:
{
std::string m_filename;
bool m_isTemporaryFile = false;
BookmarkLoaderInfo() {}
BookmarkLoaderInfo() = default;
BookmarkLoaderInfo(std::string const & filename, bool isTemporaryFile)
: m_filename(filename), m_isTemporaryFile(isTemporaryFile)
{}
@ -437,7 +439,5 @@ private:
Cloud m_bookmarkCloud;
std::map<df::MarkGroupID, std::string> m_activeSharing;
DISALLOW_COPY_AND_MOVE(BookmarkManager);
};