forked from organicmaps/organicmaps
[ios] Restore bookmarks
This commit is contained in:
parent
7d4d51ed1f
commit
f0f3d0bd8b
13 changed files with 272 additions and 14 deletions
|
@ -284,7 +284,8 @@ extension BMCViewController: BMCPermissionsCellDelegate {
|
|||
})
|
||||
case .backup:
|
||||
viewModel.grant(permission: permission)
|
||||
case .restore: assertionFailure()
|
||||
case .restore:
|
||||
viewModel.requestRestoring()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ final class BMCDefaultViewModel: NSObject {
|
|||
|
||||
private(set) var isPendingPermission = false
|
||||
private var isAuthenticated = false
|
||||
private var filesPrepared = false;
|
||||
|
||||
private var onPreparedToShareCategory: BMCViewModel.onPreparedToShareHandler?
|
||||
|
||||
|
@ -38,7 +39,7 @@ final class BMCDefaultViewModel: NSObject {
|
|||
isPendingPermission = false
|
||||
permissions = [.backup]
|
||||
} else {
|
||||
isPendingPermission = true
|
||||
isPendingPermission = false
|
||||
permissions = [.restore(BM.lastSynchronizationDate())]
|
||||
}
|
||||
}
|
||||
|
@ -222,9 +223,103 @@ extension BMCDefaultViewModel: BMCViewModel {
|
|||
func areNotificationsEnabled() -> Bool {
|
||||
return BM.areNotificationsEnabled()
|
||||
}
|
||||
|
||||
func requestRestoring() {
|
||||
BM.requestRestoring()
|
||||
}
|
||||
|
||||
func applyRestoring() {
|
||||
BM.applyRestoring()
|
||||
}
|
||||
|
||||
func cancelRestoring() {
|
||||
if filesPrepared {
|
||||
return
|
||||
}
|
||||
|
||||
BM.cancelRestoring()
|
||||
}
|
||||
}
|
||||
|
||||
extension BMCDefaultViewModel: MWMBookmarksObserver {
|
||||
func onRestoringStarted() {
|
||||
filesPrepared = false
|
||||
MWMAlertViewController.activeAlert().presentSpinnerAlert(withTitle: L("bookmarks_restore_process"))
|
||||
{ [weak self] in self?.cancelRestoring() }
|
||||
}
|
||||
|
||||
func onRestoringFilesPrepared() {
|
||||
filesPrepared = true
|
||||
}
|
||||
|
||||
func onRestoringFinished(_ result: MWMSynchronizationResult) {
|
||||
MWMAlertViewController.activeAlert().closeAlert() { [weak self] in
|
||||
switch result {
|
||||
case .networkError: fallthrough
|
||||
case .authError:
|
||||
MWMAlertViewController.activeAlert().presentDefaultAlert(withTitle: L("error_server_title"),
|
||||
message: L("error_server_message"),
|
||||
rightButtonTitle: L("try_again"),
|
||||
leftButtonTitle: L("cancel")) {
|
||||
[weak self] in
|
||||
self?.requestRestoring()
|
||||
}
|
||||
|
||||
case .diskError:
|
||||
MWMAlertViewController.activeAlert().presentInternalErrorAlert()
|
||||
|
||||
case .userInterrupted: break
|
||||
case .success:
|
||||
guard let s = self else { return }
|
||||
s.setCategories()
|
||||
s.view.update(sections: [.categories])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func onRestoringRequest(_ result: MWMRestoringRequestResult, backupDate date: Date?) {
|
||||
MWMAlertViewController.activeAlert().closeAlert() {
|
||||
switch result {
|
||||
case .noInternet: MWMAlertViewController.activeAlert().presentNoConnectionAlert()
|
||||
|
||||
case .backupExists:
|
||||
guard let date = date else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .short
|
||||
formatter.timeStyle = .none
|
||||
let message = String(coreFormat: L("bookmarks_message_backuped_user"),
|
||||
arguments: [formatter.string(from: date)])
|
||||
|
||||
MWMAlertViewController.activeAlert().presentDefaultAlert(withTitle: L("bookmarks_restore_title"),
|
||||
message: message,
|
||||
rightButtonTitle: L("restore"),
|
||||
leftButtonTitle: L("cancel"))
|
||||
{ [weak self] in
|
||||
MWMAlertViewController.activeAlert().presentSpinnerAlert(withTitle: L("bookmarks_restore_process")) {
|
||||
[weak self] in
|
||||
self?.cancelRestoring()
|
||||
}
|
||||
self?.applyRestoring()
|
||||
}
|
||||
|
||||
case .noBackup:
|
||||
MWMAlertViewController.activeAlert().presentDefaultAlert(withTitle: L("bookmarks_restore_empty_title"),
|
||||
message: L("bookmarks_restore_empty_message"),
|
||||
rightButtonTitle: L("ok"),
|
||||
leftButtonTitle: nil,
|
||||
rightButtonAction: nil)
|
||||
|
||||
case .notEnoughDiskSpace: MWMAlertViewController.activeAlert().presentNotEnoughSpaceAlert()
|
||||
|
||||
case .requestError: assertionFailure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func onBookmarksLoadFinished() {
|
||||
loadData()
|
||||
convertAllKMLIfNeeded()
|
||||
|
|
|
@ -48,4 +48,8 @@ protocol BMCViewModel: AnyObject {
|
|||
|
||||
func setNotificationsEnabled(_ enabled: Bool)
|
||||
func areNotificationsEnabled() -> Bool
|
||||
|
||||
func requestRestoring()
|
||||
func applyRestoring()
|
||||
func cancelRestoring()
|
||||
}
|
||||
|
|
|
@ -30,7 +30,18 @@ final class BMCPermissionsCell: MWMTableViewCell {
|
|||
case .backup:
|
||||
label.text = L("bookmarks_message_authorized_user")
|
||||
button.setTitle(L("bookmarks_backup").uppercased(), for: .normal)
|
||||
case .restore: assertionFailure()
|
||||
case let .restore(date):
|
||||
if let date = date {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .short
|
||||
formatter.timeStyle = .none
|
||||
label.text = String(coreFormat: L("bookmarks_message_backuped_user"),
|
||||
arguments: [formatter.string(from: date)])
|
||||
} else {
|
||||
label.text = L("bookmarks_message_unbackuped_user")
|
||||
}
|
||||
|
||||
button.setTitle(L("bookmarks_restore"), for: .normal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,13 @@
|
|||
- (void)presentSpinnerAlertWithTitle:(nonnull NSString *)title cancel:(nullable MWMVoidBlock)cancel;
|
||||
- (void)presentBookmarkConversionErrorAlert;
|
||||
|
||||
- (void)presentDefaultAlertWithTitle:(nonnull NSString *)title
|
||||
message:(nullable NSString *)message
|
||||
rightButtonTitle:(nonnull NSString *)rightButtonTitle
|
||||
leftButtonTitle:(nullable NSString *)leftButtonTitle
|
||||
rightButtonAction:(nullable MWMVoidBlock)action;
|
||||
|
||||
|
||||
- (void)closeAlert:(nullable MWMVoidBlock)completion;
|
||||
|
||||
- (nonnull instancetype)init __attribute__((unavailable("call -initWithViewController: instead!")));
|
||||
|
|
|
@ -248,6 +248,19 @@ static NSString * const kAlertControllerNibIdentifier = @"MWMAlertViewController
|
|||
[self displayAlert:[MWMAlert bookmarkConversionErrorAlert]];
|
||||
}
|
||||
|
||||
- (void)presentDefaultAlertWithTitle:(nonnull NSString *)title
|
||||
message:(nullable NSString *)message
|
||||
rightButtonTitle:(nonnull NSString *)rightButtonTitle
|
||||
leftButtonTitle:(nullable NSString *)leftButtonTitle
|
||||
rightButtonAction:(nullable MWMVoidBlock)action
|
||||
{
|
||||
[self displayAlert:[MWMAlert defaultAlertWithTitle:title
|
||||
message:message
|
||||
rightButtonTitle:rightButtonTitle
|
||||
leftButtonTitle:leftButtonTitle
|
||||
rightButtonAction:action]];
|
||||
}
|
||||
|
||||
- (void)displayAlert:(MWMAlert *)alert
|
||||
{
|
||||
// TODO(igrechuhin): Remove this check on location manager refactoring.
|
||||
|
|
|
@ -43,6 +43,12 @@
|
|||
+ (MWMAlert *)spinnerAlertWithTitle:(NSString *)title cancel:(MWMVoidBlock)cancel;
|
||||
+ (MWMAlert *)bookmarkConversionErrorAlert;
|
||||
|
||||
+ (MWMAlert *)defaultAlertWithTitle:(NSString *)title
|
||||
message:(NSString *)message
|
||||
rightButtonTitle:(NSString *)rightButtonTitle
|
||||
leftButtonTitle:(NSString *)leftButtonTitle
|
||||
rightButtonAction:(MWMVoidBlock)action;
|
||||
|
||||
- (void)close:(MWMVoidBlock)completion;
|
||||
|
||||
- (void)setNeedsCloseAlertAfterEnterBackground;
|
||||
|
|
|
@ -185,6 +185,20 @@
|
|||
return [MWMDefaultAlert bookmarkConversionErrorAlert];
|
||||
}
|
||||
|
||||
+ (MWMAlert *)defaultAlertWithTitle:(NSString *)title
|
||||
message:(NSString *)message
|
||||
rightButtonTitle:(NSString *)rightButtonTitle
|
||||
leftButtonTitle:(NSString *)leftButtonTitle
|
||||
rightButtonAction:(MWMVoidBlock)action
|
||||
{
|
||||
return [MWMDefaultAlert defaultAlertWithTitle:title
|
||||
message:message
|
||||
rightButtonTitle:rightButtonTitle
|
||||
leftButtonTitle:leftButtonTitle
|
||||
rightButtonAction:action
|
||||
statisticsEvent:nil];
|
||||
}
|
||||
|
||||
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
|
||||
{
|
||||
// Should override this method if you want custom relayout after rotation.
|
||||
|
|
|
@ -40,4 +40,11 @@
|
|||
+ (instancetype)convertBookmarksWithCount:(NSUInteger)count okBlock:(MWMVoidBlock)okBlock;
|
||||
+ (instancetype)bookmarkConversionErrorAlert;
|
||||
|
||||
+ (instancetype)defaultAlertWithTitle:(nonnull NSString *)title
|
||||
message:(nullable NSString *)message
|
||||
rightButtonTitle:(nonnull NSString *)rightButtonTitle
|
||||
leftButtonTitle:(nullable NSString *)leftButtonTitle
|
||||
rightButtonAction:(nullable MWMVoidBlock)action
|
||||
statisticsEvent:(nullable NSString *)statisticsEvent;
|
||||
|
||||
@end
|
||||
|
|
|
@ -40,6 +40,8 @@ static NSString * const kStatBooking = @"Booking.com";
|
|||
static NSString * const kStatBookmarkCreated = @"Bookmark. Bookmark created";
|
||||
static NSString * const kStatBookmarks = @"Bookmarks";
|
||||
static NSString * const kStatBookmarksAuthRequestError = @"Bookmarks_SyncProposal_error";
|
||||
static NSString * const kStatBookmarksRestoreProposalCancel = @"Bookmarks_RestoreProposal_cancel";
|
||||
static NSString * const kStatBookmarksRestoreProposalClick = @"Bookmarks_RestoreProposal_click";
|
||||
static NSString * const kStatBookmarksAuthRequestSuccess = @"Bookmarks_SyncProposal_enabled";
|
||||
static NSString * const kStatBookmarksRestoreProposalError = @"Bookmarks_RestoreProposal_error";
|
||||
static NSString * const kStatBookmarksRestoreProposalSuccess = @"Bookmarks_RestoreProposal_success";
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
+ (void)setNotificationsEnabled:(BOOL)enabled;
|
||||
+ (BOOL)areNotificationsEnabled;
|
||||
|
||||
+ (void)requestRestoring;
|
||||
+ (void)applyRestoring;
|
||||
+ (void)cancelRestoring;
|
||||
|
||||
- (instancetype)init __attribute__((unavailable("call +manager instead")));
|
||||
- (instancetype)copy __attribute__((unavailable("call +manager instead")));
|
||||
- (instancetype)copyWithZone:(NSZone *)zone __attribute__((unavailable("call +manager instead")));
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "coding/internal/file_data.hpp"
|
||||
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace
|
||||
|
@ -132,7 +134,16 @@ NSString * const CloudErrorToString(Cloud::SynchronizationResult result)
|
|||
auto onSynchronizationStarted = [](Cloud::SynchronizationType type)
|
||||
{
|
||||
if (type == Cloud::SynchronizationType::Backup)
|
||||
{
|
||||
[Statistics logEvent:kStatBookmarksSyncStarted];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[MWMBookmarksManager manager] loopObservers:^(Observer observer) {
|
||||
if ([observer respondsToSelector:@selector(onRestoringStarted)])
|
||||
[observer onRestoringStarted];
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
auto onSynchronizationFinished = [](Cloud::SynchronizationType type, Cloud::SynchronizationResult result,
|
||||
|
@ -143,21 +154,33 @@ NSString * const CloudErrorToString(Cloud::SynchronizationResult result)
|
|||
[Statistics logEvent:type == Cloud::SynchronizationType::Backup ? kStatBookmarksSyncSuccess :
|
||||
kStatBookmarksRestoreProposalSuccess];
|
||||
}
|
||||
else
|
||||
else if (auto const error = CloudErrorToString(result))
|
||||
{
|
||||
NSString * const errorType = CloudErrorToString(result);
|
||||
if (errorType != nil)
|
||||
{
|
||||
[Statistics logEvent:type == Cloud::SynchronizationType::Backup ? kStatBookmarksSyncError :
|
||||
kStatBookmarksRestoreProposalError
|
||||
withParameters:@{kStatType: errorType, kStatError: @(errorStr.c_str())}];
|
||||
}
|
||||
[Statistics logEvent:type == Cloud::SynchronizationType::Backup ? kStatBookmarksSyncError :
|
||||
kStatBookmarksRestoreProposalError
|
||||
withParameters:@{kStatType: error, kStatError: @(errorStr.c_str())}];
|
||||
}
|
||||
|
||||
if (type != Cloud::SynchronizationType::Restore)
|
||||
return;
|
||||
|
||||
[[MWMBookmarksManager manager] loopObservers:^(Observer observer) {
|
||||
if ([observer respondsToSelector:@selector(onRestoringFinished:)])
|
||||
[observer onRestoringFinished:static_cast<MWMSynchronizationResult>(my::Key(result))];
|
||||
}];
|
||||
};
|
||||
|
||||
auto onRestoreRequested = [](Cloud::RestoringRequestResult result, uint64_t backupTimestampInMs)
|
||||
{
|
||||
if (result == Cloud::RestoringRequestResult::NoBackup)
|
||||
auto const res = static_cast<MWMRestoringRequestResult>(my::Key(result));
|
||||
NSDate * date = nil;
|
||||
|
||||
if (result == Cloud::RestoringRequestResult::BackupExists)
|
||||
{
|
||||
auto const interval = static_cast<NSTimeInterval>(backupTimestampInMs / 1000.);
|
||||
date = [NSDate dateWithTimeIntervalSince1970:interval];
|
||||
}
|
||||
else if (result == Cloud::RestoringRequestResult::NoBackup)
|
||||
{
|
||||
[Statistics logEvent:kStatBookmarksRestoreProposalError
|
||||
withParameters:@{kStatType: kStatNoBackup, kStatError: @("")}];
|
||||
|
@ -167,11 +190,19 @@ NSString * const CloudErrorToString(Cloud::SynchronizationResult result)
|
|||
[Statistics logEvent:kStatBookmarksRestoreProposalError
|
||||
withParameters:@{kStatType: kStatDisk, kStatError: @("Not enough disk space")}];
|
||||
}
|
||||
|
||||
[[MWMBookmarksManager manager] loopObservers:^(Observer observer) {
|
||||
if ([observer respondsToSelector:@selector(onRestoringRequest:backupDate:)])
|
||||
[observer onRestoringRequest:res backupDate:date];
|
||||
}];
|
||||
};
|
||||
|
||||
auto onRestoredFilesPrepared = []()
|
||||
auto onRestoredFilesPrepared = []
|
||||
{
|
||||
//TODO: On this callback we have to block cancel button in restore dialog if such button exists.
|
||||
[[MWMBookmarksManager manager] loopObservers:^(Observer observer) {
|
||||
if ([observer respondsToSelector:@selector(onRestoringFilesPrepared)])
|
||||
[observer onRestoringFilesPrepared];
|
||||
}];
|
||||
};
|
||||
|
||||
bm.SetCloudHandlers(std::move(onSynchronizationStarted), std::move(onSynchronizationFinished),
|
||||
|
@ -333,6 +364,47 @@ NSString * const CloudErrorToString(Cloud::SynchronizationResult result)
|
|||
GetFramework().GetBookmarkManager().SetCloudEnabled(enabled);
|
||||
}
|
||||
|
||||
+ (void)requestRestoring
|
||||
{
|
||||
auto const status = Platform::ConnectionStatus();
|
||||
auto statusStr = [](Platform::EConnectionType type) -> NSString * {
|
||||
switch (type)
|
||||
{
|
||||
case Platform::EConnectionType::CONNECTION_NONE:
|
||||
return kStatOffline;
|
||||
case Platform::EConnectionType::CONNECTION_WWAN:
|
||||
return kStatMobile;
|
||||
case Platform::EConnectionType::CONNECTION_WIFI:
|
||||
return kStatWifi;
|
||||
}
|
||||
} (status);
|
||||
|
||||
[Statistics logEvent:kStatBookmarksRestoreProposalClick
|
||||
withParameters:@{kStatNetwork : statusStr}];
|
||||
|
||||
if (status == Platform::EConnectionType::CONNECTION_NONE)
|
||||
{
|
||||
[self.manager loopObservers:^(Observer observer) {
|
||||
if ([observer respondsToSelector:@selector(onRestoringRequest:backupDate:)])
|
||||
[observer onRestoringRequest:MWMRestoringRequestResultNoInternet backupDate:nil];
|
||||
}];
|
||||
return;
|
||||
}
|
||||
|
||||
GetFramework().GetBookmarkManager().RequestCloudRestoring();
|
||||
}
|
||||
|
||||
+ (void)applyRestoring
|
||||
{
|
||||
GetFramework().GetBookmarkManager().ApplyCloudRestoring();
|
||||
}
|
||||
|
||||
+ (void)cancelRestoring
|
||||
{
|
||||
[Statistics logEvent:kStatBookmarksRestoreProposalCancel];
|
||||
GetFramework().GetBookmarkManager().CancelCloudRestoring();
|
||||
}
|
||||
|
||||
- (void)loopObservers:(TLoopBlock)block
|
||||
{
|
||||
for (Observer observer in self.observers)
|
||||
|
|
|
@ -1,10 +1,32 @@
|
|||
#import "MWMTypes.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MWMRestoringRequestResult)
|
||||
{
|
||||
MWMRestoringRequestResultBackupExists,
|
||||
MWMRestoringRequestResultNoBackup,
|
||||
MWMRestoringRequestResultNotEnoughDiskSpace,
|
||||
MWMRestoringRequestResultNoInternet,
|
||||
MWMRestoringRequestResultRequestError
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MWMSynchronizationResult)
|
||||
{
|
||||
MWMSynchronizationResultSuccess,
|
||||
MWMSynchronizationResultAuthError,
|
||||
MWMSynchronizationResultNetworkError,
|
||||
MWMSynchronizationResultDiskError,
|
||||
MWMSynchronizationResultUserInterrupted
|
||||
};
|
||||
|
||||
@protocol MWMBookmarksObserver<NSObject>
|
||||
|
||||
- (void)onConversionFinish:(BOOL)success;
|
||||
|
||||
@optional
|
||||
- (void)onRestoringRequest:(MWMRestoringRequestResult)result backupDate:(NSDate * _Nullable)date;
|
||||
- (void)onRestoringFinished:(MWMSynchronizationResult)result;
|
||||
- (void)onRestoringStarted;
|
||||
- (void)onRestoringFilesPrepared;
|
||||
- (void)onBookmarksLoadFinished;
|
||||
- (void)onBookmarksFileLoadSuccess;
|
||||
- (void)onBookmarksCategoryDeleted:(MWMMarkGroupID)groupId;
|
||||
|
|
Loading…
Add table
Reference in a new issue