forked from organicmaps/organicmaps-tmp
[ios] New place page
This commit is contained in:
parent
c3b17e75f7
commit
54798069b3
52 changed files with 3158 additions and 182 deletions
|
@ -219,7 +219,7 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
BookmarksVC * bvc = [[BookmarksVC alloc] initWithCategory:indexPath.row];
|
||||
BookmarksVC * bvc = [[BookmarksVC alloc] initWithCategory:static_cast<int>(indexPath.row)];
|
||||
[self.navigationController pushViewController:bvc animated:YES];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
@interface BookmarksVC : MWMTableViewController <UITextFieldDelegate>
|
||||
{
|
||||
size_t m_categoryIndex;
|
||||
int m_categoryIndex;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCategory:(size_t)index;
|
||||
- (instancetype)initWithCategory:(int)index;
|
||||
|
||||
@end
|
||||
|
|
|
@ -38,7 +38,7 @@ extern NSString * const kBookmarksChangedNotification = @"BookmarksChangedNotifi
|
|||
|
||||
@implementation BookmarksVC
|
||||
|
||||
- (instancetype)initWithCategory:(size_t)index
|
||||
- (instancetype)initWithCategory:(int)index
|
||||
{
|
||||
self = [super initWithStyle:UITableViewStyleGrouped];
|
||||
if (self)
|
||||
|
@ -236,7 +236,7 @@ extern NSString * const kBookmarksChangedNotification = @"BookmarksChangedNotifi
|
|||
// Same as "Close".
|
||||
MapViewController * mapVC = self.navigationController.viewControllers.firstObject;
|
||||
mapVC.controlsManager.searchHidden = YES;
|
||||
f.ShowBookmark(BookmarkAndCategory(m_categoryIndex, indexPath.row));
|
||||
f.ShowBookmark({static_cast<int>(indexPath.row), m_categoryIndex});
|
||||
[self.navigationController popToRootViewControllerAnimated:YES];
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ extern NSString * const kBookmarksChangedNotification = @"BookmarksChangedNotifi
|
|||
}
|
||||
else
|
||||
{
|
||||
BookmarkAndCategory bookmarkAndCategory = BookmarkAndCategory(m_categoryIndex, indexPath.row);
|
||||
BookmarkAndCategory bookmarkAndCategory{static_cast<int>(indexPath.row), m_categoryIndex};
|
||||
NSValue * value = [NSValue valueWithBytes:&bookmarkAndCategory objCType:@encode(BookmarkAndCategory)];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:BOOKMARK_DELETED_NOTIFICATION object:value];
|
||||
BookmarkCategory::Guard guard(*cat);
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
[super viewDidLoad];
|
||||
NSAssert(self.category, @"Category can't be nil!");
|
||||
NSAssert(self.delegate, @"Delegate can't be nil!");
|
||||
NSAssert(IsValid(m_bac), @"Invalid BookmarkAndCategory's instance!");
|
||||
NSAssert(m_bac.IsValid(), @"Invalid BookmarkAndCategory's instance!");
|
||||
self.title = L(@"bookmark_sets");
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@
|
|||
if (cat)
|
||||
cell.textLabel.text = @(cat->GetName().c_str());
|
||||
|
||||
if (m_bac.first == indexPath.row)
|
||||
if (m_bac.m_categoryIndex == indexPath.row)
|
||||
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
||||
else
|
||||
cell.accessoryType = UITableViewCellAccessoryNone;
|
||||
|
@ -85,11 +85,11 @@
|
|||
- (void)moveBookmarkToSetWithIndex:(int)setIndex
|
||||
{
|
||||
BookmarkAndCategory bac;
|
||||
bac.second = static_cast<int>(GetFramework().MoveBookmark(m_bac.second, m_bac.first, setIndex));
|
||||
bac.first = setIndex;
|
||||
bac.m_bookmarkIndex = static_cast<int>(GetFramework().MoveBookmark(m_bac.m_bookmarkIndex, m_bac.m_categoryIndex, setIndex));
|
||||
bac.m_categoryIndex = setIndex;
|
||||
m_bac = bac;
|
||||
|
||||
BookmarkCategory const * category = GetFramework().GetBookmarkManager().GetBmCategory(bac.first);
|
||||
BookmarkCategory const * category = GetFramework().GetBookmarkManager().GetBmCategory(bac.m_categoryIndex);
|
||||
self.category = @(category->GetName().c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
@class MapViewController;
|
||||
@class MWMPlacePageEntity;
|
||||
@protocol MWMFeatureHolder;
|
||||
|
||||
@interface MWMMapViewControlsManager : NSObject
|
||||
|
||||
|
@ -20,8 +21,8 @@
|
|||
@property(nonatomic) MWMBottomMenuState menuState;
|
||||
@property(nonatomic) MWMBottomMenuState menuRestoreState;
|
||||
@property(nonatomic, readonly) MWMNavigationDashboardState navigationState;
|
||||
@property(nonatomic, readonly) MWMPlacePageEntity * placePageEntity;
|
||||
@property(nonatomic) BOOL searchHidden;
|
||||
@property(nonatomic) BOOL isDirectionViewHidden;
|
||||
|
||||
- (instancetype)init __attribute__((unavailable("init is not available")));
|
||||
- (instancetype)initWithParentController:(MapViewController *)controller;
|
||||
|
@ -40,8 +41,6 @@
|
|||
|
||||
#pragma mark - MWMPlacePageViewManager
|
||||
|
||||
@property(nonatomic, readonly) BOOL isDirectionViewShown;
|
||||
|
||||
- (void)dismissPlacePage;
|
||||
- (void)showPlacePage:(place_page::Info const &)info;
|
||||
- (void)addPlacePageViews:(NSArray *)views;
|
||||
|
@ -68,4 +67,8 @@
|
|||
- (void)searchFrameUpdated:(CGRect)frame;
|
||||
- (void)searchText:(NSString *)text forInputLocale:(NSString *)locale;
|
||||
|
||||
#pragma mark - MWMFeatureHolder
|
||||
|
||||
- (id<MWMFeatureHolder>)featureHolder;
|
||||
|
||||
@end
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#import "MWMFrameworkListener.h"
|
||||
#import "MWMObjectsCategorySelectorController.h"
|
||||
#import "MWMPlacePageEntity.h"
|
||||
#import "MWMPlacePageManager.h"
|
||||
#import "MWMPlacePageViewManager.h"
|
||||
#import "MWMRoutePreview.h"
|
||||
#import "MWMRouter.h"
|
||||
|
@ -42,7 +43,7 @@ extern NSString * const kAlohalyticsTapEventKey;
|
|||
|
||||
@property(nonatomic) MWMSideButtons * sideButtons;
|
||||
@property(nonatomic) MWMBottomMenuViewController * menuController;
|
||||
@property(nonatomic) MWMPlacePageViewManager * placePageManager;
|
||||
@property(nonatomic) id<MWMPlacePageProtocol> placePageManager;
|
||||
@property(nonatomic) MWMNavigationDashboardManager * navigationManager;
|
||||
@property(nonatomic) MWMSearchManager * searchManager;
|
||||
|
||||
|
@ -84,7 +85,7 @@ extern NSString * const kAlohalyticsTapEventKey;
|
|||
searchManagerState != MWMSearchManagerStateHidden) ||
|
||||
self.navigationState == MWMNavigationDashboardStatePlanning ||
|
||||
self.navigationState == MWMNavigationDashboardStateReady ||
|
||||
self.menuState == MWMBottomMenuStateActive || self.isDirectionViewShown ||
|
||||
self.menuState == MWMBottomMenuStateActive || !self.isDirectionViewHidden ||
|
||||
(isNightMode && self.navigationState != MWMNavigationDashboardStateHidden) ||
|
||||
MapsAppDelegate.theApp.routingPlaneMode != MWMRoutingPlaneModeNone;
|
||||
return (isLight || (!isLight && isNightMode)) ? UIStatusBarStyleLightContent
|
||||
|
@ -292,12 +293,19 @@ extern NSString * const kAlohalyticsTapEventKey;
|
|||
{
|
||||
if (IPAD)
|
||||
return;
|
||||
CGSize const ownerViewSize = self.ownerController.view.size;
|
||||
if (ownerViewSize.width > ownerViewSize.height)
|
||||
if (isIOS7)
|
||||
{
|
||||
CGFloat const leftBound = frame.origin.x + frame.size.width;
|
||||
self.menuController.leftBound = leftBound;
|
||||
[MWMNavigationDashboardManager manager].leftBound = leftBound;
|
||||
CGSize const ownerViewSize = self.ownerController.view.size;
|
||||
if (ownerViewSize.width > ownerViewSize.height)
|
||||
{
|
||||
CGFloat const leftBound = frame.origin.x + frame.size.width;
|
||||
self.menuController.leftBound = leftBound;
|
||||
[MWMNavigationDashboardManager manager].leftBound = leftBound;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self.sideButtons setBottomBound:frame.origin.y];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -459,11 +467,13 @@ extern NSString * const kAlohalyticsTapEventKey;
|
|||
return _menuController;
|
||||
}
|
||||
|
||||
- (MWMPlacePageViewManager *)placePageManager
|
||||
- (id)placePageManager
|
||||
{
|
||||
auto const PlacePageClass = isIOS7 || IPAD ? [MWMPlacePageViewManager class] : [MWMPlacePageManager class];
|
||||
|
||||
if (!_placePageManager)
|
||||
_placePageManager =
|
||||
[[MWMPlacePageViewManager alloc] initWithViewController:self.ownerController];
|
||||
[[PlacePageClass alloc] initWithViewController:self.ownerController];
|
||||
return _placePageManager;
|
||||
}
|
||||
|
||||
|
@ -526,12 +536,6 @@ extern NSString * const kAlohalyticsTapEventKey;
|
|||
}
|
||||
|
||||
- (MWMNavigationDashboardState)navigationState { return self.navigationManager.state; }
|
||||
- (MWMPlacePageEntity *)placePageEntity { return self.placePageManager.entity; }
|
||||
- (BOOL)isDirectionViewShown
|
||||
{
|
||||
return _placePageManager ? _placePageManager.isDirectionViewShown : NO;
|
||||
}
|
||||
|
||||
- (void)setTopBound:(CGFloat)topBound
|
||||
{
|
||||
if (IPAD)
|
||||
|
@ -558,4 +562,11 @@ extern NSString * const kAlohalyticsTapEventKey;
|
|||
searchHidden ? MWMSearchManagerStateHidden : MWMSearchManagerStateDefault;
|
||||
}
|
||||
|
||||
#pragma mark - MWMFeatureHolder
|
||||
|
||||
- (id<MWMFeatureHolder>)featureHolder
|
||||
{
|
||||
return self.placePageManager;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
- (IBAction)openBookmarks
|
||||
{
|
||||
BookmarksVC * bvc = [[BookmarksVC alloc] initWithCategory:self.index];
|
||||
BookmarksVC * bvc = [[BookmarksVC alloc] initWithCategory:static_cast<int>(self.index)];
|
||||
UINavigationController * rootVC = (UINavigationController *)UIApplication.sharedApplication.delegate.window.rootViewController;
|
||||
[rootVC pushViewController:bvc animated:YES];
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#import "Common.h"
|
||||
#import "MWMActionBarButton.h"
|
||||
#import "MWMButton.h"
|
||||
#import "UIColor+MapsMeColor.h"
|
||||
|
@ -95,7 +96,8 @@ NSString * titleForButton(EButton type, BOOL isSelected)
|
|||
button.delegate = delegate;
|
||||
button.type = type;
|
||||
[view addSubview:button];
|
||||
button.autoresizingMask = UIViewAutoresizingNone;
|
||||
if (isIOS7)
|
||||
button.autoresizingMask = UIViewAutoresizingNone;
|
||||
[button configButton:isSelected];
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#import "MWMPlacePage.h"
|
||||
#import "MWMPlacePageActionBar.h"
|
||||
#import "MWMPlacePageBookmarkCell.h"
|
||||
#import "MWMPlacePageBookmarkDelegate.h"
|
||||
#import "MWMPlacePageButtonCell.h"
|
||||
#import "MWMPlacePageEntity.h"
|
||||
#import "MWMPlacePageInfoCell.h"
|
||||
|
|
12
iphone/Maps/Classes/MWMBookmarkCell.h
Normal file
12
iphone/Maps/Classes/MWMBookmarkCell.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#import "MWMTableViewCell.h"
|
||||
|
||||
@protocol MWMPlacePageButtonsProtocol, MWMPlacePageCellUpdateProtocol;
|
||||
|
||||
@interface MWMBookmarkCell : MWMTableViewCell
|
||||
|
||||
- (void)configureWithText:(NSString *)text
|
||||
updateCellDelegate:(id<MWMPlacePageCellUpdateProtocol>)updateCellDelegate
|
||||
editBookmarkDelegate:(id<MWMPlacePageButtonsProtocol>)editBookmarkDelegate
|
||||
isHTML:(BOOL)isHTML;
|
||||
|
||||
@end
|
216
iphone/Maps/Classes/MWMBookmarkCell.mm
Normal file
216
iphone/Maps/Classes/MWMBookmarkCell.mm
Normal file
|
@ -0,0 +1,216 @@
|
|||
#import "MWMPlacePageCellUpdateProtocol.h"
|
||||
#import "MWMBookmarkCell.h"
|
||||
|
||||
#import "MWMPlacePageProtocol.h"
|
||||
#import "UIColor+MapsMeColor.h"
|
||||
#import "UIFont+MapsMeFonts.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
void * kContext = &kContext;
|
||||
NSString * const kTextViewContentSizeKeyPath = @"contentSize";
|
||||
|
||||
} // namespace
|
||||
|
||||
@interface MWMBookmarkCell ()
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UITextView * textView;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * spinner;
|
||||
@property(weak, nonatomic) IBOutlet UIButton * editButton;
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * gradientView;
|
||||
|
||||
@property(nonatomic) IBOutlet NSLayoutConstraint * textViewHeight;
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * moreButtonHeight;
|
||||
@property(nonatomic) IBOutlet NSLayoutConstraint * textViewZeroHeight;
|
||||
|
||||
@property(weak, nonatomic) id<MWMPlacePageCellUpdateProtocol> updateCellDelegate;
|
||||
@property(weak, nonatomic) id<MWMPlacePageButtonsProtocol> editBookmarkDelegate;
|
||||
|
||||
@property(copy, nonatomic) NSAttributedString * attributedHTML;
|
||||
|
||||
@property (nonatomic) BOOL isOpen;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MWMBookmarkCell
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
[self registerObserver];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self unregisterObserver];
|
||||
}
|
||||
|
||||
- (void)unregisterObserver
|
||||
{
|
||||
[self.textView removeObserver:self forKeyPath:kTextViewContentSizeKeyPath context:kContext];
|
||||
}
|
||||
|
||||
- (void)registerObserver
|
||||
{
|
||||
[self.textView addObserver:self forKeyPath:kTextViewContentSizeKeyPath options:NSKeyValueObservingOptionNew context:kContext];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context
|
||||
{
|
||||
if (context == kContext)
|
||||
{
|
||||
NSValue * s = change[@"new"];
|
||||
CGFloat const height = s.CGSizeValue.height;
|
||||
auto const boundedHeight = self.textViewHeight.constant;
|
||||
|
||||
if (height < boundedHeight || self.isOpen)
|
||||
[self stateOpen:YES];
|
||||
else if (height > boundedHeight && !self.isOpen)
|
||||
[self stateOpen:NO];
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self.updateCellDelegate updateCellWithForceReposition:NO];
|
||||
return;
|
||||
}
|
||||
|
||||
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
||||
}
|
||||
|
||||
- (void)configureWithText:(NSString *)text
|
||||
updateCellDelegate:(id<MWMPlacePageCellUpdateProtocol>)updateCellDelegate
|
||||
editBookmarkDelegate:(id<MWMPlacePageButtonsProtocol>)editBookmarkDelegate
|
||||
isHTML:(BOOL)isHTML
|
||||
{
|
||||
self.attributedHTML = nil;
|
||||
self.isOpen = NO;
|
||||
self.textViewHeight.active = NO;
|
||||
self.textViewZeroHeight.active = NO;
|
||||
self.updateCellDelegate = updateCellDelegate;
|
||||
self.editBookmarkDelegate = editBookmarkDelegate;
|
||||
|
||||
if (!text.length)
|
||||
{
|
||||
[self configWithEmptyDescription];
|
||||
}
|
||||
else if (isHTML)
|
||||
{
|
||||
[self configHTML:text];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self configPlain:text];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)configWithEmptyDescription
|
||||
{
|
||||
[self stopSpinner];
|
||||
|
||||
[self stateOpen:YES];
|
||||
self.textViewZeroHeight.active = YES;
|
||||
}
|
||||
|
||||
- (void)configHTML:(NSString *)text
|
||||
{
|
||||
if (self.attributedHTML)
|
||||
{
|
||||
[self stopSpinner];
|
||||
self.textViewZeroHeight.active = NO;
|
||||
self.textView.attributedText = self.attributedHTML;
|
||||
if (fabs(self.textView.contentSize.height - 0.5) < 1)
|
||||
[self.textView sizeToFit];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.textViewZeroHeight.active = YES;
|
||||
[self startSpinner];
|
||||
[self stateOpen:YES];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSDictionary<NSString *, id> * attr = @{
|
||||
NSForegroundColorAttributeName : [UIColor blackPrimaryText],
|
||||
NSFontAttributeName : [UIFont regular16]
|
||||
};
|
||||
NSError * error = nil;
|
||||
NSMutableAttributedString * str = [[NSMutableAttributedString alloc]
|
||||
initWithData:[text dataUsingEncoding:NSUnicodeStringEncoding]
|
||||
options:@{
|
||||
NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType
|
||||
}
|
||||
documentAttributes:nil
|
||||
error:&error];
|
||||
if (error)
|
||||
{
|
||||
// If we failed while attempting to render html than just show plain text in bookmark.
|
||||
// Ussualy there is a problem only in iOS7.
|
||||
self.attributedHTML = [[NSAttributedString alloc] initWithString:text attributes:attr];
|
||||
}
|
||||
else
|
||||
{
|
||||
[str addAttributes:attr range:{0, str.length}];
|
||||
self.attributedHTML = str;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
[self configHTML:nil];
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)configPlain:(NSString *)text
|
||||
{
|
||||
[self stopSpinner];
|
||||
self.textView.text = text;
|
||||
}
|
||||
|
||||
- (void)stateOpen:(BOOL)isOpen
|
||||
{
|
||||
self.moreButtonHeight.constant = isOpen ? 0 : 33;
|
||||
self.textViewHeight.active = !isOpen;
|
||||
self.gradientView.hidden = isOpen;
|
||||
}
|
||||
|
||||
- (void)startSpinner
|
||||
{
|
||||
// self.textViewZeroHeight.active = YES;
|
||||
self.editButton.hidden = YES;
|
||||
NSUInteger const animationImagesCount = 12;
|
||||
NSMutableArray * animationImages = [NSMutableArray arrayWithCapacity:animationImagesCount];
|
||||
NSString * postfix = [UIColor isNightMode] ? @"dark" : @"light";
|
||||
for (NSUInteger i = 0; i < animationImagesCount; ++i)
|
||||
animationImages[i] =
|
||||
[UIImage imageNamed:[NSString stringWithFormat:@"Spinner_%@_%@", @(i + 1), postfix]];
|
||||
|
||||
self.spinner.animationDuration = 0.8;
|
||||
self.spinner.animationImages = animationImages;
|
||||
self.spinner.hidden = NO;
|
||||
[self.spinner startAnimating];
|
||||
}
|
||||
|
||||
- (void)stopSpinner
|
||||
{
|
||||
[self.spinner stopAnimating];
|
||||
self.editButton.hidden = NO;
|
||||
self.spinner.hidden = YES;
|
||||
}
|
||||
|
||||
- (IBAction)moreTap
|
||||
{
|
||||
self.isOpen = YES;
|
||||
[self stateOpen:YES];
|
||||
[self setNeedsLayout];
|
||||
// [self.delegate updateCellWithForceReposition:NO];
|
||||
}
|
||||
|
||||
- (IBAction)editTap
|
||||
{
|
||||
[self.editBookmarkDelegate editBookmark];
|
||||
}
|
||||
|
||||
@end
|
|
@ -13,6 +13,8 @@
|
|||
- (instancetype)initWithManager:(MWMPlacePageViewManager *)manager;
|
||||
- (void)setDirectionArrowTransform:(CGAffineTransform)transform;
|
||||
|
||||
- (void)show;
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder __attribute__((unavailable("initWithCoder is not available")));
|
||||
- (instancetype)initWithFrame:(CGRect)frame __attribute__((unavailable("initWithFrame is not available")));
|
||||
- (instancetype)init __attribute__((unavailable("init is not available")));
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#import "MapsAppDelegate.h"
|
||||
#import "MapViewController.h"
|
||||
#import "MWMMapViewControlsManager.h"
|
||||
#import "MWMDirectionView.h"
|
||||
#import "MWMPlacePageViewManager.h"
|
||||
#import "UIFont+MapsMeFonts.h"
|
||||
|
@ -34,6 +37,36 @@ static CGFloat const kDirectionArrowSide = IPAD ? 260. : 160.;
|
|||
self.directionArrow.autoresizingMask = UIViewAutoresizingNone;
|
||||
}
|
||||
|
||||
- (void)show
|
||||
{
|
||||
UIView * superview = [MapsAppDelegate theApp].mapViewController.view;
|
||||
[superview addSubview:self];
|
||||
[superview endEditing:YES];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)didMoveToSuperview
|
||||
{
|
||||
[super didMoveToSuperview];
|
||||
|
||||
MapsAppDelegate * app = [MapsAppDelegate theApp];
|
||||
|
||||
MWMMapViewControlsManager * manager = [MWMMapViewControlsManager manager];
|
||||
|
||||
if (self.superview)
|
||||
{
|
||||
[app disableStandby];
|
||||
manager.isDirectionViewHidden = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
[app enableStandby];
|
||||
manager.isDirectionViewHidden = YES;
|
||||
}
|
||||
|
||||
[app.mapViewController updateStatusBarStyle];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
UIView * superview = self.superview;
|
||||
|
@ -122,7 +155,7 @@ static CGFloat const kDirectionArrowSide = IPAD ? 260. : 160.;
|
|||
{
|
||||
// Prevent super call to stop event propagation
|
||||
// [super touchesBegan:touches withEvent:event];
|
||||
[self.manager hideDirectionView];
|
||||
[self removeFromSuperview];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#import "MWMTableViewController.h"
|
||||
|
||||
@class MWMPlacePageViewManager;
|
||||
@class MWMPlacePageData;
|
||||
|
||||
@interface MWMEditBookmarkController : MWMTableViewController
|
||||
|
||||
@property (weak, nonatomic) MWMPlacePageData * data;
|
||||
@property (nonatomic) MWMPlacePageViewManager * manager;
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#import "Common.h"
|
||||
#import "MWMBookmarkTitleCell.h"
|
||||
#import "MWMButtonCell.h"
|
||||
#import "MWMBookmarkColorViewController.h"
|
||||
#import "MWMEditBookmarkController.h"
|
||||
#import "MWMNoteCell.h"
|
||||
#import "MWMPlacePageData.h"
|
||||
#import "MWMPlacePageEntity.h"
|
||||
#import "MWMPlacePageViewManager.h"
|
||||
#import "SelectSetVC.h"
|
||||
|
@ -50,13 +52,23 @@ enum RowInMetaInfo
|
|||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
NSAssert(self.manager, @"Entity can't be nil!");
|
||||
MWMPlacePageEntity * en = self.manager.entity;
|
||||
self.cachedDescription = en.bookmarkDescription;
|
||||
self.cachedTitle = en.bookmarkTitle;
|
||||
self.cachedCategory = en.bookmarkCategory;
|
||||
self.cachedColor = en.bookmarkColor;
|
||||
m_cachedBac = en.bac;
|
||||
NSAssert(self.manager || self.data, @"Entity and data can't be nil both!");
|
||||
if (isIOS7 || IPAD)
|
||||
{
|
||||
MWMPlacePageEntity * en = self.manager.entity;
|
||||
self.cachedDescription = en.bookmarkDescription;
|
||||
self.cachedTitle = en.bookmarkTitle;
|
||||
self.cachedCategory = en.bookmarkCategory;
|
||||
self.cachedColor = en.bookmarkColor;
|
||||
m_cachedBac = en.bac;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.cachedDescription = self.data.bookmarkDescription;
|
||||
self.cachedTitle = self.data.externalTitle ? self.data.externalTitle : self.data.title;
|
||||
self.cachedCategory = self.data.bookmarkCategory;
|
||||
self.cachedColor = self.data.bookmarkColor;
|
||||
}
|
||||
|
||||
[self configNavBar];
|
||||
[self registerCells];
|
||||
|
@ -95,14 +107,40 @@ enum RowInMetaInfo
|
|||
- (void)onSave
|
||||
{
|
||||
[self.view endEditing:YES];
|
||||
MWMPlacePageEntity * en = self.manager.entity;
|
||||
en.bookmarkDescription = self.cachedDescription;
|
||||
en.bookmarkColor = self.cachedColor;
|
||||
en.bookmarkCategory = self.cachedCategory;
|
||||
en.bookmarkTitle = self.cachedTitle;
|
||||
en.bac = m_cachedBac;
|
||||
[en synchronize];
|
||||
[self.manager reloadBookmark];
|
||||
if (isIOS7 || IPAD)
|
||||
{
|
||||
MWMPlacePageEntity * en = self.manager.entity;
|
||||
en.bookmarkDescription = self.cachedDescription;
|
||||
en.bookmarkColor = self.cachedColor;
|
||||
en.bookmarkCategory = self.cachedCategory;
|
||||
en.bookmarkTitle = self.cachedTitle;
|
||||
en.bac = m_cachedBac;
|
||||
[en synchronize];
|
||||
[self.manager reloadBookmark];
|
||||
}
|
||||
else
|
||||
{
|
||||
Framework & f = GetFramework();
|
||||
auto const bac = self.data.bac;
|
||||
BookmarkCategory * category = f.GetBmCategory(bac.m_categoryIndex);
|
||||
if (!category)
|
||||
return;
|
||||
|
||||
{
|
||||
BookmarkCategory::Guard guard(*category);
|
||||
Bookmark * bookmark =
|
||||
static_cast<Bookmark *>(guard.m_controller.GetUserMarkForEdit(bac.m_bookmarkIndex));
|
||||
if (!bookmark)
|
||||
return;
|
||||
|
||||
bookmark->SetType(self.cachedColor.UTF8String);
|
||||
bookmark->SetDescription(self.cachedDescription.UTF8String);
|
||||
bookmark->SetName(self.cachedTitle.UTF8String);
|
||||
}
|
||||
|
||||
category->SaveToKMLFile();
|
||||
f.UpdatePlacePageInfoForCurrentSelection();
|
||||
}
|
||||
[self backTap];
|
||||
}
|
||||
|
||||
|
|
32
iphone/Maps/Classes/MWMOpeningHours.h
Normal file
32
iphone/Maps/Classes/MWMOpeningHours.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
namespace osmoh
|
||||
{
|
||||
struct Day
|
||||
{
|
||||
Day(NSString * workingDays, NSString * workingTimes, NSString * breaks) : m_workingDays(workingDays),
|
||||
m_workingTimes(workingTimes),
|
||||
m_breaks(breaks) {}
|
||||
|
||||
explicit Day(NSString * workingDays) : m_workingDays(workingDays),
|
||||
m_isOpen(false) {}
|
||||
|
||||
NSString * TodayTime() const
|
||||
{
|
||||
return m_workingTimes ? [NSString stringWithFormat:@"%@ %@", m_workingDays, m_workingTimes] : m_workingDays;
|
||||
}
|
||||
|
||||
NSString * m_workingDays;
|
||||
NSString * m_workingTimes;
|
||||
NSString * m_breaks;
|
||||
bool m_isOpen = true;
|
||||
};
|
||||
|
||||
} // namespace osmoh
|
||||
|
||||
#include "std/string.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
@interface MWMOpeningHours : NSObject
|
||||
|
||||
+ (vector<osmoh::Day>)processRawString:(NSString *)str;
|
||||
|
||||
@end
|
128
iphone/Maps/Classes/MWMOpeningHours.mm
Normal file
128
iphone/Maps/Classes/MWMOpeningHours.mm
Normal file
|
@ -0,0 +1,128 @@
|
|||
#import "MWMOpeningHours.h"
|
||||
#import "MWMOpeningHoursCommon.h"
|
||||
|
||||
|
||||
#include "3party/opening_hours/opening_hours.hpp"
|
||||
#include "editor/opening_hours_ui.hpp"
|
||||
#include "editor/ui2oh.hpp"
|
||||
|
||||
using namespace editor;
|
||||
using namespace osmoh;
|
||||
|
||||
namespace
|
||||
{
|
||||
NSString * stringFromTimeSpan(Timespan const & timeSpan)
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@ - %@", stringFromTime(timeSpan.GetStart()),
|
||||
stringFromTime(timeSpan.GetEnd())];
|
||||
}
|
||||
|
||||
NSString * breaksFromClosedTime(TTimespans const & closedTimes)
|
||||
{
|
||||
NSMutableString * breaks = [@"" mutableCopy];
|
||||
for (auto & ct : closedTimes)
|
||||
{
|
||||
[breaks appendString:@"\n"];
|
||||
[breaks appendString:stringFromTimeSpan(ct)];
|
||||
}
|
||||
return breaks.copy;
|
||||
}
|
||||
|
||||
void addToday(ui::TimeTable const & tt, vector<Day> & allDays)
|
||||
{
|
||||
NSString * workingDays;
|
||||
NSString * workingTimes;
|
||||
NSString * breaks;
|
||||
|
||||
if (tt.IsTwentyFourHours())
|
||||
{
|
||||
workingDays = L(@"twentyfour_seven");
|
||||
workingTimes = @"";
|
||||
breaks = @"";
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL const everyDay = (tt.GetOpeningDays().size() == 7);
|
||||
workingDays = everyDay ? L(@"daily") : L(@"today");
|
||||
workingTimes = stringFromTimeSpan(tt.GetOpeningTime());
|
||||
breaks = breaksFromClosedTime(tt.GetExcludeTime());
|
||||
}
|
||||
|
||||
allDays.emplace(allDays.begin(), workingDays, workingTimes, breaks);
|
||||
}
|
||||
|
||||
void addClosedToday(vector<Day> & allDays)
|
||||
{
|
||||
allDays.emplace(allDays.begin(), L(@"day_off_today"));
|
||||
}
|
||||
|
||||
void addDay(ui::TimeTable const & tt, vector<Day> & allDays)
|
||||
{
|
||||
NSString * workingDays = stringFromOpeningDays(tt.GetOpeningDays());
|
||||
NSString * workingTimes;
|
||||
NSString * breaks;
|
||||
if (tt.IsTwentyFourHours())
|
||||
{
|
||||
workingTimes = L(@"twentyfour_seven");
|
||||
}
|
||||
else
|
||||
{
|
||||
workingTimes = stringFromTimeSpan(tt.GetOpeningTime());
|
||||
breaks = breaksFromClosedTime(tt.GetExcludeTime());
|
||||
}
|
||||
allDays.emplace_back(workingDays, workingTimes, breaks);
|
||||
}
|
||||
|
||||
void addUnhandledDays(ui::TOpeningDays const & days, vector<Day> & allDays)
|
||||
{
|
||||
if (days.empty())
|
||||
return;
|
||||
|
||||
allDays.emplace_back(stringFromOpeningDays(days));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@implementation MWMOpeningHours
|
||||
|
||||
+ (vector<Day>)processRawString:(NSString *)str
|
||||
{
|
||||
ui::TimeTableSet timeTableSet;
|
||||
osmoh::OpeningHours oh(str.UTF8String);
|
||||
if (!MakeTimeTableSet(oh, timeTableSet))
|
||||
return {};
|
||||
|
||||
vector<Day> days;
|
||||
|
||||
NSCalendar * cal = [NSCalendar currentCalendar];
|
||||
cal.locale = [NSLocale currentLocale];
|
||||
|
||||
auto const timeTablesSize = timeTableSet.Size();
|
||||
auto const today = static_cast<Weekday>([cal components:NSCalendarUnitWeekday fromDate:[NSDate date]].weekday);
|
||||
auto const unhandledDays = timeTableSet.GetUnhandledDays();
|
||||
|
||||
/// Schedule contains more than one rule for all days or unhandled days.
|
||||
BOOL const isExtendedSchedule = timeTablesSize != 1 || !unhandledDays.empty();
|
||||
BOOL hasCurrentDay = NO;
|
||||
|
||||
for (auto const & tt : timeTableSet)
|
||||
{
|
||||
ui::TOpeningDays const & workingDays = tt.GetOpeningDays();
|
||||
if (workingDays.find(today) != workingDays.end())
|
||||
{
|
||||
hasCurrentDay = YES;
|
||||
addToday(tt, days);
|
||||
}
|
||||
|
||||
if (isExtendedSchedule)
|
||||
addDay(tt, days);
|
||||
}
|
||||
|
||||
if (!hasCurrentDay)
|
||||
addClosedToday(days);
|
||||
|
||||
addUnhandledDays(unhandledDays, days);
|
||||
return days;
|
||||
}
|
||||
|
||||
@end
|
10
iphone/Maps/Classes/MWMOpeningHoursCell.h
Normal file
10
iphone/Maps/Classes/MWMOpeningHoursCell.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#import "MWMTableViewCell.h"
|
||||
|
||||
@protocol MWMPlacePageCellUpdateProtocol;
|
||||
|
||||
@interface MWMOpeningHoursCell : MWMTableViewCell
|
||||
|
||||
- (void)configureWithOpeningHours:(NSString *)openningHours
|
||||
updateLayoutDelegate:(id<MWMPlacePageCellUpdateProtocol>)delegate
|
||||
isClosedNow:(BOOL)isClosedNow;
|
||||
@end
|
200
iphone/Maps/Classes/MWMOpeningHoursCell.mm
Normal file
200
iphone/Maps/Classes/MWMOpeningHoursCell.mm
Normal file
|
@ -0,0 +1,200 @@
|
|||
#import "Common.h"
|
||||
#import "MWMOpeningHours.h"
|
||||
#import "MWMOpeningHoursCell.h"
|
||||
#import "MWMPlacePageCellUpdateProtocol.h"
|
||||
|
||||
#include "std/array.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
array<NSString *, 2> kOHClasses = {{@"_MWMOHHeaderCell", @"_MWMOHSubCell"}};
|
||||
void * kContext = &kContext;
|
||||
NSString * const kTableViewContentSizeKeyPath = @"contentSize";
|
||||
|
||||
} // namespace
|
||||
|
||||
#pragma mark - _MWMOHHeaderCell
|
||||
|
||||
@interface _MWMOHHeaderCell : MWMTableViewCell
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * today;
|
||||
@property(weak, nonatomic) IBOutlet UILabel * breaks;
|
||||
@property(weak, nonatomic) IBOutlet UILabel * closedNow;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * arrowIcon;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * separator;
|
||||
|
||||
@property(copy, nonatomic) TMWMVoidBlock tapAction;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMOHHeaderCell
|
||||
|
||||
- (IBAction)extendTap
|
||||
{
|
||||
if (!self.tapAction)
|
||||
return;
|
||||
|
||||
self.tapAction();
|
||||
[UIView animateWithDuration:kDefaultAnimationDuration animations:^
|
||||
{
|
||||
self.arrowIcon.transform = CGAffineTransformIsIdentity(self.arrowIcon.transform) ?
|
||||
CGAffineTransformMakeRotation(M_PI) :
|
||||
CGAffineTransformIdentity;
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - _MWMOHSubCell
|
||||
|
||||
@interface _MWMOHSubCell :MWMTableViewCell
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * days;
|
||||
@property(weak, nonatomic) IBOutlet UILabel * schedule;
|
||||
@property(weak, nonatomic) IBOutlet UILabel * breaks;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * separator;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMOHSubCell
|
||||
|
||||
@end
|
||||
|
||||
@interface MWMOpeningHoursCell () <UITableViewDelegate, UITableViewDataSource>
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UITableView * tableView;
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * tableViewHeight;
|
||||
|
||||
@property(weak, nonatomic) id<MWMPlacePageCellUpdateProtocol> delegate;
|
||||
|
||||
@property(nonatomic) BOOL isExtended;
|
||||
@property(nonatomic) BOOL isClosedNow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MWMOpeningHoursCell
|
||||
{
|
||||
vector<osmoh::Day> m_days;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
for (auto s : kOHClasses)
|
||||
[self.tableView registerNib:[UINib nibWithNibName:s bundle:nil] forCellReuseIdentifier:s];
|
||||
|
||||
self.tableView.estimatedRowHeight = 48;
|
||||
self.tableView.rowHeight = UITableViewAutomaticDimension;
|
||||
[self registerObserver];
|
||||
}
|
||||
|
||||
- (void)configureWithOpeningHours:(NSString *)openningHours
|
||||
updateLayoutDelegate:(id<MWMPlacePageCellUpdateProtocol>)delegate
|
||||
isClosedNow:(BOOL)isClosedNow;
|
||||
{
|
||||
self.tableView.delegate = nil;
|
||||
self.tableView.dataSource = nil;
|
||||
self.delegate = delegate;
|
||||
self.isClosedNow = isClosedNow;
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^
|
||||
{
|
||||
self->m_days = [MWMOpeningHours processRawString:openningHours];
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
self.tableView.delegate = self;
|
||||
self.tableView.dataSource = self;
|
||||
[self.tableView reloadData];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - UITableView
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return self.isExtended ? m_days.size() : 1;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
auto const & day = m_days[indexPath.row];
|
||||
BOOL const isSeparatorHidden = self.isExtended ? indexPath.row == 0 : indexPath.row == m_days.size() - 1;
|
||||
if (indexPath.row == 0)
|
||||
{
|
||||
_MWMOHHeaderCell * cell = [tableView dequeueReusableCellWithIdentifier:[_MWMOHHeaderCell className]];
|
||||
cell.today.text = day.TodayTime();
|
||||
cell.breaks.text = day.m_breaks;
|
||||
cell.closedNow.text = self.isClosedNow ? L(@"closed_now") : nil;;
|
||||
if (m_days.size() > 1)
|
||||
{
|
||||
cell.tapAction = ^
|
||||
{
|
||||
self.isExtended = !self.isExtended;
|
||||
|
||||
NSMutableArray<NSIndexPath *> * ip = [@[] mutableCopy];
|
||||
|
||||
for (auto i = 1; i < self->m_days.size(); i++)
|
||||
[ip addObject:[NSIndexPath indexPathForRow:i inSection:0]];
|
||||
|
||||
if (self.isExtended)
|
||||
[self.tableView insertRowsAtIndexPaths:ip withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
else
|
||||
[self.tableView deleteRowsAtIndexPaths:ip withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
};
|
||||
cell.arrowIcon.hidden = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.tapAction = nil;
|
||||
cell.arrowIcon.hidden = YES;
|
||||
}
|
||||
cell.separator.hidden = isSeparatorHidden;
|
||||
return cell;
|
||||
}
|
||||
else
|
||||
{
|
||||
_MWMOHSubCell * cell = [tableView dequeueReusableCellWithIdentifier:[_MWMOHSubCell className]];
|
||||
cell.days.text = day.m_workingDays;
|
||||
cell.schedule.text = day.m_workingTimes ? day.m_workingTimes : L(@"closed");
|
||||
cell.breaks.text = day.m_breaks;
|
||||
cell.separator.hidden = isSeparatorHidden;
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Observer's methods
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self unregisterObserver];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context
|
||||
{
|
||||
if (context == kContext)
|
||||
{
|
||||
NSValue * s = change[@"new"];
|
||||
CGFloat const height = s.CGSizeValue.height;
|
||||
self.tableViewHeight.constant = height;
|
||||
[self setNeedsLayout];
|
||||
[self.delegate updateCellWithForceReposition:NO];
|
||||
return;
|
||||
}
|
||||
|
||||
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
||||
}
|
||||
|
||||
- (void)unregisterObserver
|
||||
{
|
||||
[self.tableView removeObserver:self forKeyPath:kTableViewContentSizeKeyPath context:kContext];
|
||||
}
|
||||
|
||||
- (void)registerObserver
|
||||
{
|
||||
[self.tableView addObserver:self forKeyPath:kTableViewContentSizeKeyPath options:NSKeyValueObservingOptionNew context:kContext];
|
||||
}
|
||||
@end
|
31
iphone/Maps/Classes/MWMPPView.h
Normal file
31
iphone/Maps/Classes/MWMPPView.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma mark - MWMPPScrollView
|
||||
|
||||
@protocol MWMPlacePageViewUpdateProtocol <NSObject>
|
||||
|
||||
- (void)updateWithHeight:(CGFloat)height;
|
||||
|
||||
@end
|
||||
|
||||
@interface MWMPPScrollView : UIScrollView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame inactiveView:(UIView *)inactiveView;
|
||||
|
||||
@property(weak, nonatomic) UIView * inactiveView;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - MWMPPView
|
||||
|
||||
@interface MWMPPView : UIView
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * top;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * spinner;
|
||||
@property(weak, nonatomic) IBOutlet UITableView * tableView;
|
||||
|
||||
@property(nonatomic) CGFloat currentContentHeight;
|
||||
@property(nonatomic) id<MWMPlacePageViewUpdateProtocol> delegate;
|
||||
|
||||
- (void)hideTableView:(BOOL)isHidden;
|
||||
|
||||
@end
|
||||
|
101
iphone/Maps/Classes/MWMPPView.mm
Normal file
101
iphone/Maps/Classes/MWMPPView.mm
Normal file
|
@ -0,0 +1,101 @@
|
|||
#import "MWMPPView.h"
|
||||
#import "UIColor+MapsMeColor.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
void * kContext = &kContext;
|
||||
NSString * const kTableViewContentSizeKeyPath = @"contentSize";
|
||||
|
||||
} // namespace
|
||||
|
||||
#pragma mark - MWMPPScrollView
|
||||
|
||||
@implementation MWMPPScrollView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame inactiveView:(UIView *)inactiveView
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self)
|
||||
_inactiveView = inactiveView;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
|
||||
{
|
||||
if (point.y > [self convertRect:self.inactiveView.bounds fromView:self.inactiveView].origin.y)
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - MWMPPView
|
||||
|
||||
@implementation MWMPPView
|
||||
|
||||
- (void)hideTableView:(BOOL)isHidden
|
||||
{
|
||||
if (isHidden)
|
||||
{
|
||||
self.tableView.alpha = 0.;
|
||||
self.spinner.hidden = NO;
|
||||
[self.spinner startAnimating];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.tableView.alpha = 1.;
|
||||
self.spinner.hidden = YES;
|
||||
[self.spinner stopAnimating];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context
|
||||
{
|
||||
if (context == kContext)
|
||||
{
|
||||
NSValue * s = change[@"new"];
|
||||
CGFloat const height = s.CGSizeValue.height;
|
||||
if (fabs(height - self.currentContentHeight) > 0.5)
|
||||
{
|
||||
self.currentContentHeight = height;
|
||||
self.height = height + self.top.height;
|
||||
[self setNeedsLayout];
|
||||
[self.delegate updateWithHeight:self.height];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
[self.tableView addObserver:self forKeyPath:kTableViewContentSizeKeyPath options:NSKeyValueObservingOptionNew context:kContext];
|
||||
|
||||
self.tableView.estimatedRowHeight = 44.;
|
||||
self.tableView.rowHeight = UITableViewAutomaticDimension;
|
||||
|
||||
self.tableView.contentInset = {.top = -36};
|
||||
|
||||
NSUInteger const animationImagesCount = 12;
|
||||
NSMutableArray * animationImages = [NSMutableArray arrayWithCapacity:animationImagesCount];
|
||||
NSString * postfix = [UIColor isNightMode] ? @"dark" : @"light";
|
||||
for (NSUInteger i = 0; i < animationImagesCount; ++i)
|
||||
animationImages[i] = [UIImage imageNamed:[NSString stringWithFormat:@"Spinner_%@_%@", @(i+1), postfix]];
|
||||
|
||||
self.spinner.animationDuration = 0.8;
|
||||
self.spinner.animationImages = animationImages;
|
||||
[self.spinner startAnimating];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self.tableView removeObserver:self forKeyPath:kTableViewContentSizeKeyPath context:kContext];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
static NSString * const kPlacePageNibIdentifier = @"PlacePageView";
|
||||
static NSString * const kPlacePageViewCenterKeyPath = @"center";
|
||||
extern NSString * const kPP2BookmarkEditingSegue = @"PP2BookmarkEditing";
|
||||
static NSString * const kPP2BookmarkEditingSegue = @"PP2BookmarkEditing";
|
||||
extern NSString * const kPP2BookmarkEditingIPADSegue = @"PP2BookmarkEditingIPAD";
|
||||
|
||||
@interface MWMPlacePage ()
|
||||
|
|
|
@ -1,7 +1,25 @@
|
|||
@class MWMPlacePageViewManager;
|
||||
@class MWMPlacePageData;
|
||||
|
||||
@protocol MWMActionBarSharedData <NSObject>
|
||||
|
||||
- (BOOL)isBookmark;
|
||||
- (BOOL)isBooking;
|
||||
- (BOOL)isApi;
|
||||
- (BOOL)isMyPosition;
|
||||
- (NSString *)title;
|
||||
- (NSString *)subtitle;
|
||||
- (NSString *)phoneNumber;
|
||||
|
||||
@end
|
||||
|
||||
@protocol MWMActionBarProtocol;
|
||||
|
||||
@interface MWMPlacePageActionBar : SolidTouchView
|
||||
|
||||
+ (MWMPlacePageActionBar *)actionBarWithDelegate:(id<MWMActionBarProtocol>)delegate;
|
||||
- (void)configureWithData:(id<MWMActionBarSharedData>)data;
|
||||
|
||||
@property (nonatomic) BOOL isBookmark;
|
||||
|
||||
- (UIView *)shareAnchor;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#import "MWMActionBarButton.h"
|
||||
#import "MWMBasePlacePageView.h"
|
||||
#import "MWMPlacePageEntity.h"
|
||||
#import "MWMPlacePageProtocol.h"
|
||||
#import "MWMPlacePageViewManager.h"
|
||||
#import "MapViewController.h"
|
||||
#import "MapsAppDelegate.h"
|
||||
|
@ -13,12 +14,6 @@
|
|||
|
||||
extern NSString * const kAlohalyticsTapEventKey;
|
||||
|
||||
namespace
|
||||
{
|
||||
NSString * const kPlacePageActionBarNibName = @"PlacePageActionBar";
|
||||
|
||||
} // namespace
|
||||
|
||||
@interface MWMPlacePageActionBar ()<MWMActionBarButtonDelegate>
|
||||
{
|
||||
vector<EButton> m_visibleButtons;
|
||||
|
@ -30,14 +25,34 @@ NSString * const kPlacePageActionBarNibName = @"PlacePageActionBar";
|
|||
@property(weak, nonatomic) IBOutlet UIImageView * separator;
|
||||
@property(nonatomic) BOOL isPrepareRouteMode;
|
||||
|
||||
@property(weak, nonatomic) id<MWMActionBarSharedData> data;
|
||||
@property(weak, nonatomic) id<MWMActionBarProtocol> delegate;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MWMPlacePageActionBar
|
||||
|
||||
+ (MWMPlacePageActionBar *)actionBarWithDelegate:(id<MWMActionBarProtocol>)delegate
|
||||
{
|
||||
MWMPlacePageActionBar * bar = [[NSBundle.mainBundle loadNibNamed:[self className] owner:nil options:nil]
|
||||
firstObject];
|
||||
bar.delegate = delegate;
|
||||
return bar;
|
||||
}
|
||||
|
||||
- (void)configureWithData:(id<MWMActionBarSharedData>)data
|
||||
{
|
||||
self.data = data;
|
||||
self.isPrepareRouteMode = MapsAppDelegate.theApp.routingPlaneMode != MWMRoutingPlaneModeNone;
|
||||
self.isBookmark = data.isBookmark;
|
||||
[self configureButtons];
|
||||
self.autoresizingMask = UIViewAutoresizingNone;
|
||||
}
|
||||
|
||||
+ (MWMPlacePageActionBar *)actionBarForPlacePageManager:(MWMPlacePageViewManager *)placePageManager
|
||||
{
|
||||
MWMPlacePageActionBar * bar =
|
||||
[[NSBundle.mainBundle loadNibNamed:kPlacePageActionBarNibName owner:nil options:nil]
|
||||
[[NSBundle.mainBundle loadNibNamed:[self className] owner:nil options:nil]
|
||||
firstObject];
|
||||
[bar configureWithPlacePageManager:placePageManager];
|
||||
return bar;
|
||||
|
@ -56,16 +71,16 @@ NSString * const kPlacePageActionBarNibName = @"PlacePageActionBar";
|
|||
{
|
||||
m_visibleButtons.clear();
|
||||
m_additionalButtons.clear();
|
||||
MWMPlacePageEntity * entity = self.placePageManager.entity;
|
||||
NSString * phone = [entity getCellValue:MWMPlacePageCellTypePhoneNumber];
|
||||
auto data = static_cast<id<MWMActionBarSharedData>>(isIOS7 ? self.placePageManager.entity : self.data);
|
||||
NSString * phone = data.phoneNumber;
|
||||
|
||||
BOOL const isIphone = [[UIDevice currentDevice].model isEqualToString:@"iPhone"];
|
||||
BOOL const isPhoneNotEmpty = phone.length > 0;
|
||||
BOOL const isBooking = entity.isBooking;
|
||||
BOOL const isBooking = data.isBooking;
|
||||
BOOL const itHasPhoneNumber = isIphone && isPhoneNotEmpty;
|
||||
BOOL const isApi = entity.isApi;
|
||||
BOOL const isApi = data.isApi;
|
||||
BOOL const isP2P = self.isPrepareRouteMode;
|
||||
BOOL const isMyPosition = entity.isMyPosition;
|
||||
BOOL const isMyPosition = data.isMyPosition;
|
||||
|
||||
if (isMyPosition)
|
||||
{
|
||||
|
@ -171,21 +186,24 @@ NSString * const kPlacePageActionBarNibName = @"PlacePageActionBar";
|
|||
|
||||
- (void)tapOnButtonWithType:(EButton)type
|
||||
{
|
||||
MWMPlacePageViewManager * placePageManager = self.placePageManager;
|
||||
id<MWMActionBarProtocol> delegate = IPAD ? self.placePageManager : self.delegate;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case EButton::Api: [placePageManager apiBack]; break;
|
||||
case EButton::Booking: [placePageManager book:NO]; break;
|
||||
case EButton::Call: [placePageManager call]; break;
|
||||
case EButton::Api: [delegate apiBack]; break;
|
||||
case EButton::Booking: [delegate book:NO]; break;
|
||||
case EButton::Call: [delegate call]; break;
|
||||
case EButton::Bookmark:
|
||||
if (self.isBookmark)
|
||||
[placePageManager removeBookmark];
|
||||
[delegate removeBookmark];
|
||||
else
|
||||
[placePageManager addBookmark];
|
||||
[delegate addBookmark];
|
||||
|
||||
self.isBookmark = !self.isBookmark;
|
||||
break;
|
||||
case EButton::RouteFrom: [placePageManager routeFrom]; break;
|
||||
case EButton::RouteTo: [placePageManager routeTo]; break;
|
||||
case EButton::Share: [placePageManager share]; break;
|
||||
case EButton::RouteFrom: [delegate routeFrom]; break;
|
||||
case EButton::RouteTo: [delegate routeTo]; break;
|
||||
case EButton::Share: [delegate share]; break;
|
||||
case EButton::More: [self showActionSheet]; break;
|
||||
case EButton::Spacer: break;
|
||||
}
|
||||
|
@ -196,16 +214,16 @@ NSString * const kPlacePageActionBarNibName = @"PlacePageActionBar";
|
|||
- (void)showActionSheet
|
||||
{
|
||||
NSString * cancel = L(@"cancel");
|
||||
MWMPlacePageEntity * entity = self.placePageManager.entity;
|
||||
BOOL const isTitleNotEmpty = entity.title.length > 0;
|
||||
NSString * title = isTitleNotEmpty ? entity.title : entity.subtitle;
|
||||
NSString * subtitle = isTitleNotEmpty ? entity.subtitle : nil;
|
||||
auto data = static_cast<id<MWMActionBarSharedData>>(IPAD ? self.placePageManager.entity : self.data);
|
||||
BOOL const isTitleNotEmpty = data.title.length > 0;
|
||||
NSString * title = isTitleNotEmpty ? data.title : data.subtitle;
|
||||
NSString * subtitle = isTitleNotEmpty ? data.subtitle : nil;
|
||||
|
||||
UIViewController * vc = static_cast<UIViewController *>([MapViewController controller]);
|
||||
NSMutableArray<NSString *> * titles = [@[] mutableCopy];
|
||||
for (auto const buttonType : m_additionalButtons)
|
||||
{
|
||||
BOOL const isSelected = buttonType == EButton::Bookmark ? self.isBookmark : NO;
|
||||
BOOL const isSelected = buttonType == EButton::Bookmark ? data.isBookmark : NO;
|
||||
if (NSString * title = titleForButton(buttonType, isSelected))
|
||||
[titles addObject:title];
|
||||
else
|
||||
|
@ -246,6 +264,10 @@ NSString * const kPlacePageActionBarNibName = @"PlacePageActionBar";
|
|||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
self.width = self.superview.width;
|
||||
if (IPAD)
|
||||
self.origin = {0, self.superview.height - 48};
|
||||
|
||||
self.separator.width = self.width;
|
||||
CGFloat const buttonWidth = self.width / self.buttons.count;
|
||||
for (UIView * button in self.buttons)
|
||||
|
@ -255,6 +277,11 @@ NSString * const kPlacePageActionBarNibName = @"PlacePageActionBar";
|
|||
}
|
||||
}
|
||||
|
||||
- (void)setFrame:(CGRect)frame
|
||||
{
|
||||
[super setFrame:frame];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (void)setIsBookmark:(BOOL)isBookmark
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
|
@ -1,13 +1,6 @@
|
|||
#import "MWMTableViewCell.h"
|
||||
|
||||
@protocol MWMPlacePageBookmarkDelegate <NSObject>
|
||||
|
||||
- (void)reloadBookmark;
|
||||
- (void)editBookmarkTap;
|
||||
- (void)moreTap;
|
||||
|
||||
@end
|
||||
|
||||
@protocol MWMPlacePageBookmarkDelegate;
|
||||
@class MWMPlacePage;
|
||||
|
||||
@interface MWMPlacePageBookmarkCell : MWMTableViewCell
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#import "MWMPlacePageBookmarkCell.h"
|
||||
#import "MWMPlacePageBookmarkDelegate.h"
|
||||
#import "Common.h"
|
||||
#import "MapViewController.h"
|
||||
#import "Statistics.h"
|
||||
|
|
8
iphone/Maps/Classes/MWMPlacePageBookmarkDelegate.h
Normal file
8
iphone/Maps/Classes/MWMPlacePageBookmarkDelegate.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
@protocol MWMPlacePageBookmarkDelegate <NSObject>
|
||||
|
||||
@required
|
||||
- (void)editBookmarkTap;
|
||||
- (void)reloadBookmark;
|
||||
- (void)moreTap;
|
||||
|
||||
@end
|
|
@ -1,10 +1,19 @@
|
|||
#import "MWMTableViewCell.h"
|
||||
#import "MWMPlacePageEntity.h"
|
||||
#import "MWMPlacePageData.h"
|
||||
|
||||
@class MWMPlacePageViewManager;
|
||||
|
||||
@protocol MWMPlacePageButtonsProtocol;
|
||||
|
||||
@interface MWMPlacePageButtonCell : MWMTableViewCell
|
||||
|
||||
- (void)config:(MWMPlacePageViewManager *)manager forType:(MWMPlacePageCellType)type;
|
||||
- (void)config:(MWMPlacePageViewManager *)manager forType:(MWMPlacePageCellType)type NS_DEPRECATED_IOS(7_0, 8_0);
|
||||
|
||||
- (void)configForRow:(place_page::ButtonsRows)row
|
||||
withDelegate:(id<MWMPlacePageButtonsProtocol>)delegate NS_AVAILABLE_IOS(8_0);
|
||||
|
||||
- (void)setEnabled:(BOOL)enabled NS_AVAILABLE_IOS(8_0);
|
||||
- (BOOL)isEnabled NS_AVAILABLE_IOS(8_0);
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#import "Common.h"
|
||||
#import "MWMPlacePageButtonCell.h"
|
||||
#import "MWMFrameworkListener.h"
|
||||
#import "MWMPlacePageViewManager.h"
|
||||
#import "UIColor+MapsMeColor.h"
|
||||
#import "MWMPlacePageProtocol.h"
|
||||
|
||||
@interface MWMPlacePageButtonCell ()<MWMFrameworkStorageObserver>
|
||||
|
||||
|
@ -10,6 +12,8 @@
|
|||
@property(nonatomic) MWMPlacePageCellType type;
|
||||
@property(nonatomic) storage::TCountryId countryId;
|
||||
|
||||
@property(weak, nonatomic) id<MWMPlacePageButtonsProtocol> delegate;
|
||||
@property(nonatomic) place_page::ButtonsRows rowType;
|
||||
@end
|
||||
|
||||
@implementation MWMPlacePageButtonCell
|
||||
|
@ -22,16 +26,59 @@
|
|||
[self refreshButtonEnabledState];
|
||||
}
|
||||
|
||||
- (void)setEnabled:(BOOL)enabled
|
||||
{
|
||||
self.titleButton.enabled = enabled;
|
||||
}
|
||||
|
||||
- (BOOL)isEnabled
|
||||
{
|
||||
return self.titleButton.isEnabled;
|
||||
}
|
||||
|
||||
- (void)configForRow:(place_page::ButtonsRows)row withDelegate:(id<MWMPlacePageButtonsProtocol>)delegate
|
||||
{
|
||||
self.delegate = delegate;
|
||||
self.rowType = row;
|
||||
switch(row)
|
||||
{
|
||||
case place_page::ButtonsRows::AddPlace:
|
||||
[self.titleButton setTitle:L(@"placepage_add_place_button") forState:UIControlStateNormal];
|
||||
break;
|
||||
case place_page::ButtonsRows::EditPlace:
|
||||
[self.titleButton setTitle:L(@"edit_place") forState:UIControlStateNormal];
|
||||
break;
|
||||
case place_page::ButtonsRows::AddBusiness:
|
||||
[self.titleButton setTitle:L(@"placepage_add_business_button") forState:UIControlStateNormal];
|
||||
break;
|
||||
case place_page::ButtonsRows::HotelDescription:
|
||||
[self.titleButton setTitle:L(@"details") forState:UIControlStateNormal];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)buttonTap
|
||||
{
|
||||
MWMPlacePageViewManager * manager = self.manager;
|
||||
switch (self.type)
|
||||
if (IPAD)
|
||||
{
|
||||
case MWMPlacePageCellTypeEditButton: [manager editPlace]; break;
|
||||
case MWMPlacePageCellTypeAddBusinessButton: [manager addBusiness]; break;
|
||||
case MWMPlacePageCellTypeAddPlaceButton: [manager addPlace]; break;
|
||||
case MWMPlacePageCellTypeBookingMore: [manager book:YES]; break;
|
||||
default: NSAssert(false, @"Incorrect cell type!"); break;
|
||||
switch (self.type)
|
||||
{
|
||||
case MWMPlacePageCellTypeEditButton: [self.manager editPlace]; break;
|
||||
case MWMPlacePageCellTypeAddBusinessButton: [self.manager addBusiness]; break;
|
||||
case MWMPlacePageCellTypeAddPlaceButton: [self.manager addPlace]; break;
|
||||
case MWMPlacePageCellTypeBookingMore: [self.manager book:YES]; break;
|
||||
default: NSAssert(false, @"Incorrect cell type!"); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace place_page;
|
||||
switch (self.rowType)
|
||||
{
|
||||
case ButtonsRows::AddPlace: [self.delegate addPlace]; break;
|
||||
case ButtonsRows::EditPlace: [self.delegate editPlace]; break;
|
||||
case ButtonsRows::AddBusiness: [self.delegate addBusiness]; break;
|
||||
case ButtonsRows::HotelDescription: [self.delegate book:YES]; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
5
iphone/Maps/Classes/MWMPlacePageCellUpdateProtocol.h
Normal file
5
iphone/Maps/Classes/MWMPlacePageCellUpdateProtocol.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
@protocol MWMPlacePageCellUpdateProtocol <NSObject>
|
||||
|
||||
- (void)updateCellWithForceReposition:(BOOL)isForceReposition;
|
||||
|
||||
@end
|
103
iphone/Maps/Classes/MWMPlacePageData.h
Normal file
103
iphone/Maps/Classes/MWMPlacePageData.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
#include "map/place_page_info.hpp"
|
||||
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace place_page
|
||||
{
|
||||
enum class Sections
|
||||
{
|
||||
Preview,
|
||||
Bookmark,
|
||||
Metainfo,
|
||||
Buttons
|
||||
};
|
||||
|
||||
enum class MetainfoRows
|
||||
{
|
||||
OpeningHours,
|
||||
Phone,
|
||||
Address,
|
||||
Website,
|
||||
Email,
|
||||
Cuisine,
|
||||
Operator,
|
||||
Internet,
|
||||
Coordinate
|
||||
};
|
||||
|
||||
enum class ButtonsRows
|
||||
{
|
||||
AddBusiness,
|
||||
EditPlace,
|
||||
AddPlace,
|
||||
HotelDescription
|
||||
};
|
||||
|
||||
enum class OpeningHours
|
||||
{
|
||||
AllDay,
|
||||
Open,
|
||||
Closed,
|
||||
Unknown
|
||||
};
|
||||
|
||||
} // namespace place_page_data
|
||||
|
||||
/// ViewModel for place page.
|
||||
@interface MWMPlacePageData : NSObject
|
||||
|
||||
// ready callback will be called from main queue.
|
||||
- (instancetype)initWithPlacePageInfo:(place_page::Info const &)info;
|
||||
|
||||
- (void)updateBookmarkStatus:(BOOL)isBookmark;
|
||||
|
||||
/// Country id for changing place page's fields which depend on application state.
|
||||
- (storage::TCountryId const &)countryId;
|
||||
- (FeatureID const &)featureId;
|
||||
|
||||
// Regular
|
||||
- (NSString *)title;
|
||||
- (NSString *)subtitle;
|
||||
- (place_page::OpeningHours)schedule;
|
||||
- (NSString *)address;
|
||||
|
||||
// Booking
|
||||
- (NSString *)bookingRating;
|
||||
- (NSString *)bookingApproximatePricing;
|
||||
- (NSURL *)bookingURL;
|
||||
- (NSURL *)bookingDescriptionURL;
|
||||
- (NSString *)hotelId;
|
||||
- (void)assignOnlinePriceToLabel:(UILabel *)label;
|
||||
|
||||
// API
|
||||
- (NSString *)apiURL;
|
||||
|
||||
// Bookmark
|
||||
- (NSString *)externalTitle;
|
||||
- (NSString *)bookmarkColor;
|
||||
- (NSString *)bookmarkDescription;
|
||||
- (NSString *)bookmarkCategory;
|
||||
- (BookmarkAndCategory)bac;
|
||||
|
||||
// Table view's data
|
||||
- (vector<place_page::Sections> const &)sections;
|
||||
- (vector<place_page::MetainfoRows> const &)metainfoRows;
|
||||
- (vector<place_page::ButtonsRows> const &)buttonsRows;
|
||||
|
||||
// Table view metainfo rows
|
||||
- (NSString *)stringForRow:(place_page::MetainfoRows)row;
|
||||
|
||||
// Helpers
|
||||
- (NSString *)phoneNumber;
|
||||
- (BOOL)isBookmark;
|
||||
- (BOOL)isApi;
|
||||
- (BOOL)isBooking;
|
||||
- (BOOL)isHTMLDescription;
|
||||
- (BOOL)isMyPosition;
|
||||
|
||||
// Coordinates
|
||||
- (m2::PointD const &)mercator;
|
||||
- (ms::LatLon)latLon;
|
||||
+ (void)toggleCoordinateSystem;
|
||||
|
||||
@end
|
406
iphone/Maps/Classes/MWMPlacePageData.mm
Normal file
406
iphone/Maps/Classes/MWMPlacePageData.mm
Normal file
|
@ -0,0 +1,406 @@
|
|||
#import "MWMPlacePageData.h"
|
||||
|
||||
#include "Framework.h"
|
||||
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
#include "3party/opening_hours/opening_hours.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS";
|
||||
|
||||
} // namespace
|
||||
|
||||
using namespace place_page;
|
||||
|
||||
@implementation MWMPlacePageData
|
||||
{
|
||||
Info m_info;
|
||||
|
||||
vector<Sections> m_sections;
|
||||
vector<MetainfoRows> m_metainfoRows;
|
||||
vector<ButtonsRows> m_buttonsRows;
|
||||
}
|
||||
|
||||
- (instancetype)initWithPlacePageInfo:(Info const &)info
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
m_info = info;
|
||||
[self fillSections];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)fillSections
|
||||
{
|
||||
m_sections.clear();
|
||||
m_metainfoRows.clear();
|
||||
m_buttonsRows.clear();
|
||||
|
||||
m_sections.push_back(Sections::Preview);
|
||||
|
||||
// It's bookmark.
|
||||
if (m_info.IsBookmark())
|
||||
m_sections.push_back(Sections::Bookmark);
|
||||
|
||||
// There is always at least coordinate meta field.
|
||||
m_sections.push_back(Sections::Metainfo);
|
||||
[self fillMetaInfoSection];
|
||||
|
||||
// There is at least one of these buttons.
|
||||
if (m_info.ShouldShowAddPlace() || m_info.ShouldShowEditPlace() || m_info.ShouldShowAddBusiness() || m_info.IsSponsoredHotel())
|
||||
{
|
||||
m_sections.push_back(Sections::Buttons);
|
||||
[self fillButtonsSection];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)fillMetaInfoSection
|
||||
{
|
||||
using namespace osm;
|
||||
auto const availableProperties = m_info.AvailableProperties();
|
||||
// We can't match each metadata property to its UI field and thats why we need to use our own enum.
|
||||
for (auto const p : availableProperties)
|
||||
{
|
||||
switch (p)
|
||||
{
|
||||
case Props::OpeningHours:
|
||||
m_metainfoRows.push_back(MetainfoRows::OpeningHours);
|
||||
break;
|
||||
case Props::Phone:
|
||||
m_metainfoRows.push_back(MetainfoRows::Phone);
|
||||
break;
|
||||
case Props::Website:
|
||||
m_metainfoRows.push_back(MetainfoRows::Website);
|
||||
break;
|
||||
case Props::Email:
|
||||
m_metainfoRows.push_back(MetainfoRows::Email);
|
||||
break;
|
||||
case Props::Cuisine:
|
||||
m_metainfoRows.push_back(MetainfoRows::Cuisine);
|
||||
break;
|
||||
case Props::Operator:
|
||||
m_metainfoRows.push_back(MetainfoRows::Operator);
|
||||
break;
|
||||
case Props::Internet:
|
||||
m_metainfoRows.push_back(MetainfoRows::Internet);
|
||||
break;
|
||||
|
||||
case Props::Wikipedia:
|
||||
case Props::Elevation:
|
||||
case Props::Stars:
|
||||
case Props::Flats:
|
||||
case Props::BuildingLevels:
|
||||
case Props::Fax:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto const address = m_info.GetAddress();
|
||||
if (!address.empty())
|
||||
m_metainfoRows.push_back(MetainfoRows::Address);
|
||||
|
||||
m_metainfoRows.push_back(MetainfoRows::Coordinate);
|
||||
}
|
||||
|
||||
- (void)fillButtonsSection
|
||||
{
|
||||
// We don't have to show edit, add place or business if it's booking object.
|
||||
if (m_info.IsSponsoredHotel())
|
||||
{
|
||||
m_buttonsRows.push_back(ButtonsRows::HotelDescription);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_info.ShouldShowAddPlace())
|
||||
m_buttonsRows.push_back(ButtonsRows::AddPlace);
|
||||
|
||||
if (m_info.ShouldShowEditPlace())
|
||||
m_buttonsRows.push_back(ButtonsRows::EditPlace);
|
||||
|
||||
if (m_info.ShouldShowAddBusiness())
|
||||
m_buttonsRows.push_back(ButtonsRows::AddBusiness);
|
||||
}
|
||||
|
||||
- (void)updateBookmarkStatus:(BOOL)isBookmark
|
||||
{
|
||||
auto & f = GetFramework();
|
||||
auto & bmManager = f.GetBookmarkManager();
|
||||
if (isBookmark)
|
||||
{
|
||||
auto const categoryIndex = static_cast<int>(f.LastEditedBMCategory());
|
||||
BookmarkData bmData{m_info.FormatNewBookmarkName(), f.LastEditedBMType()};
|
||||
auto const bookmarkIndex =
|
||||
static_cast<int>(bmManager.AddBookmark(categoryIndex,self.mercator, bmData));
|
||||
|
||||
auto category = f.GetBmCategory(categoryIndex);
|
||||
NSAssert(category, @"Category can't be nullptr!");
|
||||
{
|
||||
BookmarkCategory::Guard guard(*category);
|
||||
Bookmark * bookmark =
|
||||
static_cast<Bookmark *>(guard.m_controller.GetUserMarkForEdit(bookmarkIndex));
|
||||
f.FillBookmarkInfo(*bookmark, {bookmarkIndex, categoryIndex}, m_info);
|
||||
}
|
||||
m_sections.insert(m_sections.begin() + 1, Sections::Bookmark);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const bac = m_info.GetBookmarkAndCategory();
|
||||
auto category = bmManager.GetBmCategory(bac.m_categoryIndex);
|
||||
NSAssert(category, @"Category can't be nullptr!");
|
||||
{
|
||||
BookmarkCategory::Guard guard(*category);
|
||||
guard.m_controller.DeleteUserMark(bac.m_bookmarkIndex);
|
||||
}
|
||||
category->SaveToKMLFile();
|
||||
|
||||
m_info.m_bac = {};
|
||||
m_sections.erase(remove(m_sections.begin(), m_sections.end(), Sections::Bookmark));
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
- (storage::TCountryId const &)countryId
|
||||
{
|
||||
return m_info.m_countryId;
|
||||
}
|
||||
|
||||
- (FeatureID const &)featureId
|
||||
{
|
||||
return m_info.GetID();
|
||||
}
|
||||
|
||||
- (NSString *)title
|
||||
{
|
||||
return @(m_info.GetTitle().c_str());
|
||||
}
|
||||
|
||||
- (NSString *)subtitle
|
||||
{
|
||||
return @(m_info.GetSubtitle().c_str());
|
||||
}
|
||||
|
||||
- (place_page::OpeningHours)schedule;
|
||||
{
|
||||
auto const raw = m_info.GetOpeningHours();
|
||||
if (raw.empty())
|
||||
return place_page::OpeningHours::Unknown;
|
||||
|
||||
auto const t = time(nullptr);
|
||||
osmoh::OpeningHours oh(raw);
|
||||
if (oh.IsValid())
|
||||
{
|
||||
|
||||
if (oh.IsTwentyFourHours())
|
||||
return place_page::OpeningHours::AllDay;
|
||||
else if (oh.IsOpen(t))
|
||||
return place_page::OpeningHours::Open;
|
||||
else if (oh.IsClosed(t))
|
||||
return place_page::OpeningHours::Closed;
|
||||
else
|
||||
return place_page::OpeningHours::Unknown;
|
||||
}
|
||||
else
|
||||
{
|
||||
return place_page::OpeningHours::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)bookingRating
|
||||
{
|
||||
return m_info.IsHotel() ? @(m_info.GetRatingFormatted().c_str()) : nil;
|
||||
}
|
||||
|
||||
- (NSString *)bookingApproximatePricing
|
||||
{
|
||||
return m_info.IsHotel() ? @(m_info.GetApproximatePricing().c_str()) : nil;
|
||||
}
|
||||
|
||||
- (NSURL *)bookingURL
|
||||
{
|
||||
return m_info.IsSponsoredHotel() ? [NSURL URLWithString:@(m_info.m_sponsoredBookingUrl.c_str())] : nil;
|
||||
}
|
||||
|
||||
- (NSURL *)bookingDescriptionURL
|
||||
{
|
||||
return m_info.IsSponsoredHotel() ? [NSURL URLWithString:@(m_info.m_sponsoredDescriptionUrl.c_str())] : nil;
|
||||
}
|
||||
|
||||
- (NSString *)hotelId
|
||||
{
|
||||
return m_info.IsSponsoredHotel() ? @(m_info.GetMetadata().Get(feature::Metadata::FMD_SPONSORED_ID).c_str())
|
||||
: nil;
|
||||
}
|
||||
|
||||
- (void)assignOnlinePriceToLabel:(UILabel *)label
|
||||
{
|
||||
NSAssert(m_info.IsSponsoredHotel(), @"Online price must be assigned to booking object!");
|
||||
if (Platform::ConnectionStatus() == Platform::EConnectionType::CONNECTION_NONE)
|
||||
return;
|
||||
|
||||
NSNumberFormatter * currencyFormatter = [[NSNumberFormatter alloc] init];
|
||||
if (currencyFormatter.currencyCode.length != 3)
|
||||
currencyFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
|
||||
|
||||
currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
|
||||
currencyFormatter.maximumFractionDigits = 0;
|
||||
|
||||
string const currency = currencyFormatter.currencyCode.UTF8String;
|
||||
auto & api = GetFramework().GetBookingApi();
|
||||
|
||||
auto const func = [self, label, currency, currencyFormatter](string const & minPrice, string const & priceCurrency)
|
||||
{
|
||||
if (currency != priceCurrency)
|
||||
return;
|
||||
|
||||
NSNumberFormatter * decimalFormatter = [[NSNumberFormatter alloc] init];
|
||||
decimalFormatter.numberStyle = NSNumberFormatterDecimalStyle;
|
||||
|
||||
NSString * currencyString = [currencyFormatter stringFromNumber:[decimalFormatter numberFromString:
|
||||
[@(minPrice.c_str()) stringByReplacingOccurrencesOfString:@"."
|
||||
withString:decimalFormatter.decimalSeparator]]];
|
||||
|
||||
NSString * pattern = [L(@"place_page_starting_from") stringByReplacingOccurrencesOfString:@"%s" withString:@"%@"];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
label.text = [NSString stringWithFormat:pattern, currencyString];
|
||||
});
|
||||
};
|
||||
|
||||
api.GetMinPrice(self.hotelId.UTF8String, currency, func);
|
||||
}
|
||||
|
||||
- (NSString *)address
|
||||
{
|
||||
return @(m_info.GetAddress().c_str());
|
||||
}
|
||||
|
||||
- (NSString *)apiURL
|
||||
{
|
||||
return @(m_info.GetApiUrl().c_str());
|
||||
}
|
||||
|
||||
- (NSString *)externalTitle
|
||||
{
|
||||
return m_info.IsBookmark() && m_info.m_bookmarkTitle != m_info.GetTitle() ?
|
||||
@(m_info.m_bookmarkTitle.c_str())
|
||||
: nil;
|
||||
}
|
||||
|
||||
- (NSString *)bookmarkColor
|
||||
{
|
||||
return m_info.IsBookmark() ? @(m_info.m_bookmarkColorName.c_str()) : nil;;
|
||||
}
|
||||
|
||||
- (NSString *)bookmarkDescription
|
||||
{
|
||||
return m_info.IsBookmark() ? @(m_info.m_bookmarkDescription.c_str()) : nil;
|
||||
}
|
||||
|
||||
- (NSString *)bookmarkCategory
|
||||
{
|
||||
return m_info.IsBookmark() ? @(m_info.m_bookmarkCategoryName.c_str()) : nil;;
|
||||
}
|
||||
|
||||
- (BookmarkAndCategory)bac;
|
||||
{
|
||||
return m_info.IsBookmark() ? m_info.m_bac : BookmarkAndCategory();
|
||||
}
|
||||
|
||||
- (vector<Sections> const &)sections
|
||||
{
|
||||
return m_sections;
|
||||
}
|
||||
|
||||
- (vector<MetainfoRows> const &)metainfoRows
|
||||
{
|
||||
return m_metainfoRows;
|
||||
}
|
||||
|
||||
- (vector<ButtonsRows> const &)buttonsRows
|
||||
{
|
||||
return m_buttonsRows;
|
||||
}
|
||||
|
||||
- (NSString *)stringForRow:(MetainfoRows)row
|
||||
{
|
||||
switch (row)
|
||||
{
|
||||
case MetainfoRows::OpeningHours:
|
||||
return @(m_info.GetOpeningHours().c_str());
|
||||
case MetainfoRows::Phone:
|
||||
return @(m_info.GetPhone().c_str());
|
||||
case MetainfoRows::Address:
|
||||
return @(m_info.GetAddress().c_str());
|
||||
case MetainfoRows::Website:
|
||||
return @(m_info.GetWebsite().c_str());
|
||||
case MetainfoRows::Email:
|
||||
return @(m_info.GetEmail().c_str());
|
||||
case MetainfoRows::Cuisine:
|
||||
return @(strings::JoinStrings(m_info.GetCuisines(), Info::kSubtitleSeparator).c_str());
|
||||
case MetainfoRows::Operator:
|
||||
return @(m_info.GetOperator().c_str());
|
||||
case MetainfoRows::Internet:
|
||||
return L(@"WiFi_available");
|
||||
case MetainfoRows::Coordinate:
|
||||
return @(m_info.GetFormattedCoordinate([[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsLatLonAsDMSKey]).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Helpres
|
||||
|
||||
- (NSString *)phoneNumber
|
||||
{
|
||||
return @(m_info.GetPhone().c_str());
|
||||
}
|
||||
|
||||
- (BOOL)isBookmark
|
||||
{
|
||||
return m_info.IsBookmark();
|
||||
}
|
||||
|
||||
- (BOOL)isApi
|
||||
{
|
||||
return m_info.HasApiUrl();
|
||||
}
|
||||
|
||||
- (BOOL)isBooking
|
||||
{
|
||||
return m_info.IsHotel();
|
||||
}
|
||||
|
||||
- (BOOL)isMyPosition
|
||||
{
|
||||
return m_info.IsMyPosition();
|
||||
}
|
||||
|
||||
- (BOOL)isHTMLDescription
|
||||
{
|
||||
return strings::IsHTML(m_info.m_bookmarkDescription);
|
||||
}
|
||||
|
||||
#pragma mark - Coordinates
|
||||
|
||||
- (m2::PointD const &)mercator
|
||||
{
|
||||
return m_info.GetMercator();
|
||||
}
|
||||
|
||||
- (ms::LatLon)latLon
|
||||
{
|
||||
return m_info.GetLatLon();
|
||||
}
|
||||
|
||||
+ (void)toggleCoordinateSystem
|
||||
{
|
||||
NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
|
||||
[ud setBool:![ud boolForKey:kUserDefaultsLatLonAsDMSKey] forKey:kUserDefaultsLatLonAsDMSKey];
|
||||
[ud synchronize];
|
||||
}
|
||||
|
||||
@end
|
|
@ -61,12 +61,13 @@ using MWMPlacePageCellTypeValueMap = map<MWMPlacePageCellType, string>;
|
|||
- (BOOL)isBookmark;
|
||||
- (BOOL)isApi;
|
||||
- (BOOL)isBooking;
|
||||
- (ms::LatLon)latlon;
|
||||
- (ms::LatLon)latLon;
|
||||
- (m2::PointD const &)mercator;
|
||||
- (NSString *)apiURL;
|
||||
- (NSURL *)bookingUrl;
|
||||
- (NSURL *)bookingDescriptionUrl;
|
||||
- (NSURL *)bookingURL;
|
||||
- (NSURL *)bookingDescriptionURL;
|
||||
- (NSString * )hotelId;
|
||||
- (NSString *)phoneNumber;
|
||||
- (string)titleForNewBookmark;
|
||||
|
||||
- (instancetype)initWithInfo:(place_page::Info const &)info;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
using feature::Metadata;
|
||||
|
||||
extern NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS";
|
||||
static NSString * const kUserDefaultsLatLonAsDMSKey = @"UserDefaultsLatLonAsDMS";
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -162,9 +162,9 @@ void initFieldsMap()
|
|||
- (void)configureBookmark
|
||||
{
|
||||
auto const bac = m_info.GetBookmarkAndCategory();
|
||||
BookmarkCategory * cat = GetFramework().GetBmCategory(bac.first);
|
||||
BookmarkCategory * cat = GetFramework().GetBmCategory(bac.m_categoryIndex);
|
||||
BookmarkData const & data =
|
||||
static_cast<Bookmark const *>(cat->GetUserMark(bac.second))->GetData();
|
||||
static_cast<Bookmark const *>(cat->GetUserMark(bac.m_bookmarkIndex))->GetData();
|
||||
|
||||
self.bookmarkTitle = @(data.GetName().c_str());
|
||||
self.bookmarkCategory = @(m_info.GetBookmarkCategoryName().c_str());
|
||||
|
@ -214,11 +214,11 @@ void initFieldsMap()
|
|||
return haveField ? @(it->second.c_str()) : nil;
|
||||
}
|
||||
|
||||
- (NSURL *)bookingUrl
|
||||
- (NSURL *)bookingURL
|
||||
{
|
||||
return [self sponsoredUrl:NO];
|
||||
}
|
||||
- (NSURL *)bookingDescriptionUrl { return [self sponsoredUrl:YES]; }
|
||||
- (NSURL *)bookingDescriptionURL { return [self sponsoredUrl:YES]; }
|
||||
- (NSURL *)sponsoredUrl:(BOOL)isDescription
|
||||
{
|
||||
auto const & url =
|
||||
|
@ -238,7 +238,12 @@ void initFieldsMap()
|
|||
return self.isBooking ? @(m_info.GetMetadata().Get(Metadata::FMD_SPONSORED_ID).c_str()) : nil;
|
||||
}
|
||||
|
||||
- (ms::LatLon)latlon { return m_info.GetLatLon(); }
|
||||
- (NSString *)phoneNumber
|
||||
{
|
||||
return [self getCellValue:MWMPlacePageCellTypePhoneNumber];
|
||||
}
|
||||
|
||||
- (ms::LatLon)latLon { return m_info.GetLatLon(); }
|
||||
- (m2::PointD const &)mercator { return m_info.GetMercator(); }
|
||||
- (NSString *)apiURL { return @(m_info.GetApiUrl().c_str()); }
|
||||
- (string)titleForNewBookmark { return m_info.FormatNewBookmarkName(); }
|
||||
|
@ -246,7 +251,7 @@ void initFieldsMap()
|
|||
{
|
||||
BOOL const useDMSFormat =
|
||||
[[NSUserDefaults standardUserDefaults] boolForKey:kUserDefaultsLatLonAsDMSKey];
|
||||
ms::LatLon const latlon = self.latlon;
|
||||
ms::LatLon const latlon = self.latLon;
|
||||
return @((useDMSFormat ? measurement_utils::FormatLatLon(latlon.lat, latlon.lon)
|
||||
: measurement_utils::FormatLatLonAsDMS(latlon.lat, latlon.lon, 2))
|
||||
.c_str());
|
||||
|
@ -295,14 +300,14 @@ void initFieldsMap()
|
|||
- (void)synchronize
|
||||
{
|
||||
Framework & f = GetFramework();
|
||||
BookmarkCategory * category = f.GetBmCategory(self.bac.first);
|
||||
BookmarkCategory * category = f.GetBmCategory(self.bac.m_categoryIndex);
|
||||
if (!category)
|
||||
return;
|
||||
|
||||
{
|
||||
BookmarkCategory::Guard guard(*category);
|
||||
Bookmark * bookmark =
|
||||
static_cast<Bookmark *>(guard.m_controller.GetUserMarkForEdit(self.bac.second));
|
||||
static_cast<Bookmark *>(guard.m_controller.GetUserMarkForEdit(self.bac.m_bookmarkIndex));
|
||||
if (!bookmark)
|
||||
return;
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
#import "MWMPlacePageEntity.h"
|
||||
#import "MWMTableViewCell.h"
|
||||
|
||||
#import "MWMPlacePageData.h"
|
||||
|
||||
@interface MWMPlacePageInfoCell : MWMTableViewCell
|
||||
|
||||
- (void)configureWithType:(MWMPlacePageCellType)type info:(NSString *)info;
|
||||
- (void)configureWithType:(MWMPlacePageCellType)type info:(NSString *)info NS_DEPRECATED_IOS(7_0, 8_0);
|
||||
|
||||
- (void)configWithRow:(place_page::MetainfoRows)row data:(MWMPlacePageData *)data NS_AVAILABLE_IOS(8_0);
|
||||
|
||||
@property(weak, nonatomic, readonly) IBOutlet UIImageView * icon;
|
||||
@property(weak, nonatomic, readonly) IBOutlet id textContainer;
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
@property(weak, nonatomic) IBOutlet UIButton * upperButton;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * toggleImage;
|
||||
|
||||
@property(nonatomic) MWMPlacePageCellType type;
|
||||
@property(nonatomic) MWMPlacePageCellType type NS_DEPRECATED_IOS(7_0, 8_0);
|
||||
@property(nonatomic) place_page::MetainfoRows rowType NS_AVAILABLE_IOS(8_0);
|
||||
@property(weak, nonatomic) MWMPlacePageData * data NS_AVAILABLE_IOS(8_0);
|
||||
|
||||
@end
|
||||
|
||||
|
@ -37,8 +39,55 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)configWithRow:(place_page::MetainfoRows)row data:(MWMPlacePageData *)data;
|
||||
{
|
||||
self.rowType = row;
|
||||
self.data = data;
|
||||
NSString * name;
|
||||
switch (row)
|
||||
{
|
||||
case place_page::MetainfoRows::Address:
|
||||
self.toggleImage.hidden = YES;
|
||||
name = @"address";
|
||||
break;
|
||||
case place_page::MetainfoRows::Phone:
|
||||
self.toggleImage.hidden = YES;
|
||||
name = @"phone_number";
|
||||
break;
|
||||
case place_page::MetainfoRows::Website:
|
||||
self.toggleImage.hidden = YES;
|
||||
name = @"website";
|
||||
break;
|
||||
case place_page::MetainfoRows::Email:
|
||||
self.toggleImage.hidden = YES;
|
||||
name = @"email";
|
||||
break;
|
||||
case place_page::MetainfoRows::Cuisine:
|
||||
self.toggleImage.hidden = YES;
|
||||
name = @"cuisine";
|
||||
break;
|
||||
case place_page::MetainfoRows::Operator:
|
||||
self.toggleImage.hidden = YES;
|
||||
name = @"operator";
|
||||
break;
|
||||
case place_page::MetainfoRows::Internet:
|
||||
self.toggleImage.hidden = YES;
|
||||
name = @"wifi";
|
||||
break;
|
||||
case place_page::MetainfoRows::Coordinate:
|
||||
self.toggleImage.hidden = NO;
|
||||
name = @"coordinate";
|
||||
break;
|
||||
case place_page::MetainfoRows::OpeningHours:
|
||||
NSAssert(false, @"Incorrect cell type!");
|
||||
break;
|
||||
}
|
||||
[self configWithIconName:name data:[self.data stringForRow:row]];
|
||||
}
|
||||
|
||||
- (void)configureWithType:(MWMPlacePageCellType)type info:(NSString *)info;
|
||||
{
|
||||
self.type = type;
|
||||
NSString * typeName;
|
||||
switch (type)
|
||||
{
|
||||
|
@ -70,14 +119,18 @@
|
|||
default: NSAssert(false, @"Incorrect type!"); break;
|
||||
}
|
||||
|
||||
[self configWithIconName:typeName data:info];
|
||||
}
|
||||
|
||||
- (void)configWithIconName:(NSString *)name data:(NSString *)data
|
||||
{
|
||||
UIImage * image =
|
||||
[UIImage imageNamed:[NSString stringWithFormat:@"%@%@", @"ic_placepage_", typeName]];
|
||||
self.type = type;
|
||||
[UIImage imageNamed:[NSString stringWithFormat:@"%@%@", @"ic_placepage_", name]];
|
||||
self.icon.image = image;
|
||||
self.icon.mwm_coloring = [self.textContainer isKindOfClass:[UITextView class]]
|
||||
? MWMImageColoringBlue
|
||||
: MWMImageColoringBlack;
|
||||
[self changeText:info];
|
||||
[self changeText:data];
|
||||
UILongPressGestureRecognizer * longTap =
|
||||
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longTap:)];
|
||||
longTap.minimumPressDuration = 0.3;
|
||||
|
@ -123,25 +176,55 @@
|
|||
|
||||
- (IBAction)cellTap
|
||||
{
|
||||
switch (self.type)
|
||||
if (isIOS7)
|
||||
{
|
||||
case MWMPlacePageCellTypeURL:
|
||||
case MWMPlacePageCellTypeWebsite:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatOpenSite)];
|
||||
break;
|
||||
case MWMPlacePageCellTypeEmail:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatSendEmail)];
|
||||
break;
|
||||
case MWMPlacePageCellTypePhoneNumber:
|
||||
switch (self.type)
|
||||
{
|
||||
case MWMPlacePageCellTypeURL:
|
||||
case MWMPlacePageCellTypeWebsite:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatOpenSite)];
|
||||
break;
|
||||
case MWMPlacePageCellTypeEmail:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatSendEmail)];
|
||||
break;
|
||||
case MWMPlacePageCellTypePhoneNumber:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatCallPhoneNumber)];
|
||||
break;
|
||||
case MWMPlacePageCellTypeCoordinate:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatToggleCoordinates)];
|
||||
[self.currentEntity toggleCoordinateSystem];
|
||||
[self changeText:[self.currentEntity getCellValue:MWMPlacePageCellTypeCoordinate]];
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (self.rowType)
|
||||
{
|
||||
case place_page::MetainfoRows::Phone:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatCallPhoneNumber)];
|
||||
break;
|
||||
case MWMPlacePageCellTypeCoordinate:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatToggleCoordinates)];
|
||||
[self.currentEntity toggleCoordinateSystem];
|
||||
[self changeText:[self.currentEntity getCellValue:MWMPlacePageCellTypeCoordinate]];
|
||||
case place_page::MetainfoRows::Website:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatOpenSite)];
|
||||
break;
|
||||
case place_page::MetainfoRows::Email:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatSendEmail)];
|
||||
break;
|
||||
case place_page::MetainfoRows::Coordinate:
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatToggleCoordinates)];
|
||||
[MWMPlacePageData toggleCoordinateSystem];
|
||||
[self changeText:[self.data stringForRow:self.rowType]];
|
||||
break;
|
||||
|
||||
case place_page::MetainfoRows::Cuisine:
|
||||
case place_page::MetainfoRows::Operator:
|
||||
case place_page::MetainfoRows::OpeningHours:
|
||||
case place_page::MetainfoRows::Address:
|
||||
case place_page::MetainfoRows::Internet:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)longTap:(UILongPressGestureRecognizer *)sender
|
||||
|
|
42
iphone/Maps/Classes/MWMPlacePageLayout.h
Normal file
42
iphone/Maps/Classes/MWMPlacePageLayout.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "storage/storage_defines.hpp"
|
||||
|
||||
@protocol MWMPlacePageLayoutDelegate <NSObject>
|
||||
|
||||
- (void)onTopBoundChanged:(CGFloat)bound;
|
||||
- (void)shouldDestroyLayout;
|
||||
|
||||
@end
|
||||
|
||||
@protocol MWMPlacePageLayoutDataSource <NSObject>
|
||||
|
||||
- (NSString *)distanceToObject;
|
||||
- (void)downloadSelectedArea;
|
||||
|
||||
@end
|
||||
|
||||
@class MWMPlacePageData, MWMPPView;
|
||||
@protocol MWMPlacePageButtonsProtocol, MWMActionBarProtocol;
|
||||
|
||||
/// Helps with place page view layout and representation
|
||||
@interface MWMPlacePageLayout : NSObject
|
||||
|
||||
- (instancetype)initWithOwnerView:(UIView *)view
|
||||
delegate:(id<MWMPlacePageLayoutDelegate, MWMPlacePageButtonsProtocol, MWMActionBarProtocol>)delegate
|
||||
dataSource:(id<MWMPlacePageLayoutDataSource>)dataSource;
|
||||
|
||||
- (void)layoutWithSize:(CGSize const &)size;
|
||||
- (void)showWithData:(MWMPlacePageData *)data;
|
||||
- (void)close;
|
||||
|
||||
- (void)mwm_refreshUI;
|
||||
|
||||
- (UIView *)shareAnchor;
|
||||
|
||||
- (void)reloadBookmarkSection:(BOOL)isBookmark;
|
||||
|
||||
- (void)rotateDirectionArrowToAngle:(CGFloat)angle;
|
||||
- (void)setDistanceToObject:(NSString *)distance;
|
||||
|
||||
- (void)processDownloaderEventWithStatus:(storage::NodeStatus)status progress:(CGFloat)progress;
|
||||
|
||||
@end
|
530
iphone/Maps/Classes/MWMPlacePageLayout.mm
Normal file
530
iphone/Maps/Classes/MWMPlacePageLayout.mm
Normal file
|
@ -0,0 +1,530 @@
|
|||
#import "MWMCircularProgress.h"
|
||||
#import "MWMPlacePageActionBar.h"
|
||||
#import "MWMPlacePageCellUpdateProtocol.h"
|
||||
#import "MWMPlacePageData.h"
|
||||
#import "MWMPlacePageLayout.h"
|
||||
#import "MWMPPView.h"
|
||||
|
||||
#import "MWMBookmarkCell.h"
|
||||
#import "MWMPlacePageBookmarkCell.h"
|
||||
#import "MWMPlacePageButtonCell.h"
|
||||
#import "MWMPlacePageInfoCell.h"
|
||||
#import "MWMOpeningHoursCell.h"
|
||||
#import "MWMPlacePagePreviewCell.h"
|
||||
#import "UIColor+MapsMeColor.h"
|
||||
|
||||
#include "storage/storage.hpp"
|
||||
|
||||
#include "std/array.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class ScrollDirection { Up, Down };
|
||||
|
||||
enum class State { Bottom, Top };
|
||||
|
||||
CGFloat const kMinOffset = 64;
|
||||
CGFloat const kOpenPlacePageStopValue = 0.7;
|
||||
|
||||
array<NSString *, 1> kPreviewCells = {{@"MWMPlacePagePreviewCell"}};
|
||||
|
||||
array<NSString *, 1> kBookmarkCells = {{@"MWMBookmarkCell"}};
|
||||
|
||||
array<NSString *, 9> kMetaInfoCells = {{@"MWMOpeningHoursCell", @"PlacePageLinkCell", @"PlacePageInfoCell", @"PlacePageLinkCell", @"PlacePageLinkCell", @"PlacePageInfoCell", @"PlacePageInfoCell", @"PlacePageInfoCell", @"PlacePageInfoCell"}};
|
||||
|
||||
array<NSString *, 1> kButtonsCells = {{@"MWMPlacePageButtonCell"}};
|
||||
|
||||
NSTimeInterval const kAnimationDuration = 0.15;
|
||||
|
||||
void animate(TMWMVoidBlock animate, TMWMVoidBlock completion = nil)
|
||||
{
|
||||
[UIView animateWithDuration:kAnimationDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
|
||||
animate();
|
||||
} completion:^(BOOL finished) {
|
||||
if (completion)
|
||||
completion();
|
||||
}];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@interface MWMPlacePageLayout () <UITableViewDelegate, UITableViewDataSource,
|
||||
MWMPlacePageCellUpdateProtocol, MWMPlacePageViewUpdateProtocol>
|
||||
|
||||
@property(weak, nonatomic) MWMPlacePageData * data;
|
||||
|
||||
@property(weak, nonatomic) UIView * ownerView;
|
||||
@property(weak, nonatomic) id<MWMPlacePageLayoutDelegate, MWMPlacePageButtonsProtocol, MWMActionBarProtocol> delegate;
|
||||
@property(weak, nonatomic) id<MWMPlacePageLayoutDataSource> dataSource;
|
||||
|
||||
@property(nonatomic) MWMPPScrollView * scrollView;
|
||||
@property(nonatomic) IBOutlet MWMPPView * placePageView;
|
||||
|
||||
@property(nonatomic) ScrollDirection direction;
|
||||
@property(nonatomic) State state;
|
||||
|
||||
@property(nonatomic) CGFloat portraitOpenContentOffset;
|
||||
@property(nonatomic) CGFloat landscapeOpenContentOffset;
|
||||
@property(nonatomic) CGFloat lastContentOffset;
|
||||
@property(nonatomic) CGFloat expandedContentOffset;
|
||||
|
||||
@property(nonatomic) MWMPlacePagePreviewCell * ppPreviewCell;
|
||||
@property(nonatomic) MWMBookmarkCell * bookmarkCell;
|
||||
|
||||
@property(nonatomic) MWMPlacePageActionBar * actionBar;
|
||||
|
||||
@property(nonatomic) BOOL isPlacePageButtonsEnabled;
|
||||
@property(nonatomic) BOOL isDownloaderViewShown;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MWMPlacePageLayout
|
||||
|
||||
- (instancetype)initWithOwnerView:(UIView *)view
|
||||
delegate:(id<MWMPlacePageLayoutDelegate, MWMPlacePageButtonsProtocol, MWMActionBarProtocol>)delegate
|
||||
dataSource:(id<MWMPlacePageLayoutDataSource>)dataSource
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
_ownerView = view;
|
||||
_delegate = delegate;
|
||||
_dataSource = dataSource;
|
||||
|
||||
[[NSBundle mainBundle] loadNibNamed:[MWMPPView className] owner:self options:nil];
|
||||
auto view = self.ownerView;
|
||||
auto const & size = view.size;
|
||||
_placePageView.frame = {{0, size.height}, size};
|
||||
_placePageView.delegate = self;
|
||||
_scrollView = [[MWMPPScrollView alloc] initWithFrame:view.frame inactiveView:_placePageView];
|
||||
_portraitOpenContentOffset = MAX(size.width, size.height) * kOpenPlacePageStopValue;
|
||||
_landscapeOpenContentOffset = MIN(size.width, size.height) * kOpenPlacePageStopValue;
|
||||
[_ownerView addSubview:_scrollView];
|
||||
[_scrollView addSubview:_placePageView];
|
||||
|
||||
auto tv = _placePageView.tableView;
|
||||
[tv registerNib:[UINib nibWithNibName:kPreviewCells[0] bundle:nil] forCellReuseIdentifier:kPreviewCells[0]];
|
||||
[tv registerNib:[UINib nibWithNibName:kButtonsCells[0] bundle:nil] forCellReuseIdentifier:kButtonsCells[0]];
|
||||
[tv registerNib:[UINib nibWithNibName:kBookmarkCells[0] bundle:nil] forCellReuseIdentifier:kBookmarkCells[0]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)registerCells
|
||||
{
|
||||
auto tv = self.placePageView.tableView;
|
||||
// Register all meta info cells.
|
||||
for (auto const i : self.data.metainfoRows)
|
||||
{
|
||||
auto name = kMetaInfoCells[static_cast<size_t>(i)];
|
||||
[tv registerNib:[UINib nibWithNibName:name bundle:nil] forCellReuseIdentifier:name];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)layoutWithSize:(CGSize const &)size
|
||||
{
|
||||
self.scrollView.frame = {{}, size};
|
||||
self.placePageView.origin = {0., size.height};
|
||||
self.actionBar.frame = {{0., size.height - 48}, {size.width, 48}};
|
||||
[self.delegate onTopBoundChanged:self.scrollView.contentOffset.y];
|
||||
}
|
||||
|
||||
- (UIView *)shareAnchor
|
||||
{
|
||||
return self.actionBar.shareAnchor;
|
||||
}
|
||||
|
||||
- (void)showWithData:(MWMPlacePageData *)data
|
||||
{
|
||||
self.isPlacePageButtonsEnabled = YES;
|
||||
self.data = nil;
|
||||
self.ppPreviewCell = nil;
|
||||
self.bookmarkCell = nil;
|
||||
|
||||
self.scrollView.delegate = self;
|
||||
self.state = State::Bottom;
|
||||
|
||||
[self collapse];
|
||||
|
||||
self.data = data;
|
||||
[self.actionBar configureWithData:static_cast<id<MWMActionBarSharedData>>(self.data)];
|
||||
[self registerCells];
|
||||
[self.placePageView.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)rotateDirectionArrowToAngle:(CGFloat)angle
|
||||
{
|
||||
[self.ppPreviewCell rotateDirectionArrowToAngle:angle];
|
||||
}
|
||||
|
||||
- (void)setDistanceToObject:(NSString *)distance
|
||||
{
|
||||
[self.ppPreviewCell setDistanceToObject:distance];
|
||||
}
|
||||
|
||||
- (MWMPlacePageActionBar *)actionBar
|
||||
{
|
||||
if (!_actionBar)
|
||||
{
|
||||
_actionBar = [MWMPlacePageActionBar actionBarWithDelegate:self.delegate];
|
||||
UIView * superview = self.ownerView;
|
||||
_actionBar.origin = {0., superview.height};
|
||||
[superview addSubview:_actionBar];
|
||||
}
|
||||
return _actionBar;
|
||||
}
|
||||
|
||||
- (void)close
|
||||
{
|
||||
animate(^ {
|
||||
self.actionBar.origin = {0., self.ownerView.height};
|
||||
[self.scrollView setContentOffset:{} animated:YES];
|
||||
}, ^{
|
||||
[self.actionBar removeFromSuperview];
|
||||
self.actionBar = nil;
|
||||
[self.delegate shouldDestroyLayout];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)mwm_refreshUI
|
||||
{
|
||||
[self.placePageView mwm_refreshUI];
|
||||
[self.actionBar mwm_refreshUI];
|
||||
}
|
||||
|
||||
- (void)reloadBookmarkSection:(BOOL)isBookmark
|
||||
{
|
||||
auto tv = self.placePageView.tableView;
|
||||
NSIndexSet * set = [NSIndexSet indexSetWithIndex:static_cast<NSInteger>(place_page::Sections::Bookmark)];
|
||||
|
||||
if (isBookmark)
|
||||
{
|
||||
if (self.bookmarkCell)
|
||||
[tv reloadSections:set withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
else
|
||||
[tv insertSections:set withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
}
|
||||
else
|
||||
{
|
||||
[tv deleteSections:set withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
self.bookmarkCell = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)collapse
|
||||
{
|
||||
self.actionBar.hidden = YES;
|
||||
|
||||
[self.placePageView hideTableView:YES];
|
||||
self.scrollView.scrollEnabled = NO;
|
||||
|
||||
animate(^{
|
||||
self.actionBar.origin = {0., self.ownerView.height};
|
||||
[self.scrollView setContentOffset:{0., kMinOffset} animated:YES];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)expand
|
||||
{
|
||||
self.actionBar.hidden = NO;
|
||||
self.scrollView.scrollEnabled = YES;
|
||||
|
||||
animate(^{
|
||||
[self.placePageView hideTableView:NO];
|
||||
self.actionBar.minY = self.actionBar.superview.height - self.actionBar.height;
|
||||
self.expandedContentOffset = self.ppPreviewCell.height + self.placePageView.top.height + self.actionBar.height;
|
||||
auto const targetOffset = self.state == State::Bottom ? self.expandedContentOffset : self.topContentOffset;
|
||||
[self.scrollView setContentOffset:{0, targetOffset} animated:YES];
|
||||
});
|
||||
}
|
||||
|
||||
- (BOOL)isPortrait
|
||||
{
|
||||
auto const & s = self.ownerView.size;
|
||||
return s.height > s.width;
|
||||
}
|
||||
|
||||
- (CGFloat)topContentOffset
|
||||
{
|
||||
auto const target = self.isPortrait ? self.portraitOpenContentOffset : self.landscapeOpenContentOffset;
|
||||
if (target > self.placePageView.height)
|
||||
return self.placePageView.height;
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
#pragma mark - Downloader event
|
||||
|
||||
- (void)processDownloaderEventWithStatus:(storage::NodeStatus)status progress:(CGFloat)progress
|
||||
{
|
||||
using namespace storage;
|
||||
|
||||
switch(status)
|
||||
{
|
||||
case NodeStatus::Undefined:
|
||||
{
|
||||
self.isPlacePageButtonsEnabled = YES;
|
||||
auto const & sections = self.data.sections;
|
||||
auto const it = find(sections.begin(), sections.end(), place_page::Sections::Buttons);
|
||||
if (it != sections.end())
|
||||
{
|
||||
[self.placePageView.tableView reloadSections:[NSIndexSet indexSetWithIndex:distance(sections.begin(), it)]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
}
|
||||
|
||||
if (self.ppPreviewCell)
|
||||
[self.ppPreviewCell setDownloaderViewHidden:YES animated:NO];
|
||||
else
|
||||
self.isDownloaderViewShown = NO;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeStatus::Downloading:
|
||||
self.ppPreviewCell.mapDownloadProgress.progress = progress;
|
||||
break;
|
||||
|
||||
case NodeStatus::InQueue:
|
||||
self.ppPreviewCell.mapDownloadProgress.state = MWMCircularProgressStateSpinner;
|
||||
break;
|
||||
|
||||
case NodeStatus::Error:
|
||||
self.ppPreviewCell.mapDownloadProgress.state = MWMCircularProgressStateFailed;
|
||||
break;
|
||||
|
||||
case NodeStatus::Partly:
|
||||
break;
|
||||
|
||||
case NodeStatus::OnDiskOutOfDate:
|
||||
case NodeStatus::OnDisk:
|
||||
{
|
||||
self.isPlacePageButtonsEnabled = YES;
|
||||
auto const & sections = self.data.sections;
|
||||
auto const it = find(sections.begin(), sections.end(), place_page::Sections::Buttons);
|
||||
if (it != sections.end())
|
||||
{
|
||||
[self.placePageView.tableView reloadSections:[NSIndexSet indexSetWithIndex:distance(sections.begin(), it)]
|
||||
withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
}
|
||||
[self.ppPreviewCell setDownloaderViewHidden:YES animated:NO];
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeStatus::NotDownloaded:
|
||||
self.isPlacePageButtonsEnabled = NO;
|
||||
if (self.ppPreviewCell)
|
||||
[self.ppPreviewCell setDownloaderViewHidden:NO animated:NO];
|
||||
else
|
||||
self.isDownloaderViewShown = YES;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
- (void)scrollViewDidScroll:(MWMPPScrollView *)scrollView
|
||||
{
|
||||
if ([scrollView isEqual:self.placePageView.tableView])
|
||||
return;
|
||||
|
||||
auto const offset = scrollView.contentOffset;
|
||||
if (offset.y <= 0)
|
||||
{
|
||||
[self.scrollView removeFromSuperview];
|
||||
[self.actionBar removeFromSuperview];
|
||||
[self.delegate shouldDestroyLayout];
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset.y > self.placePageView.height + 30)
|
||||
{
|
||||
auto const bounded = self.placePageView.height + 30;
|
||||
[scrollView setContentOffset:{0, bounded}];
|
||||
[self.delegate onTopBoundChanged:bounded];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self.delegate onTopBoundChanged:offset.y];
|
||||
}
|
||||
|
||||
self.direction = self.lastContentOffset < offset.y ? ScrollDirection::Up : ScrollDirection::Down;
|
||||
self.lastContentOffset = offset.y;
|
||||
}
|
||||
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
|
||||
withVelocity:(CGPoint)velocity
|
||||
targetContentOffset:(inout CGPoint *)targetContentOffset
|
||||
{
|
||||
auto const actualOffset = scrollView.contentOffset.y;
|
||||
auto const openOffset = self.isPortrait ? self.portraitOpenContentOffset : self.landscapeOpenContentOffset;
|
||||
auto const targetOffset = (*targetContentOffset).y;
|
||||
|
||||
if (actualOffset > self.expandedContentOffset && actualOffset < openOffset)
|
||||
{
|
||||
self.state = self.direction == ScrollDirection::Up ? State::Top : State::Bottom;
|
||||
(*targetContentOffset).y = self.direction == ScrollDirection::Up ? openOffset : self.expandedContentOffset;
|
||||
}
|
||||
else if (actualOffset > openOffset && targetOffset < openOffset)
|
||||
{
|
||||
self.state = State::Top;
|
||||
(*targetContentOffset).y = openOffset;
|
||||
}
|
||||
else if (actualOffset < self.expandedContentOffset)
|
||||
{
|
||||
(*targetContentOffset).y = 0;
|
||||
animate(^{
|
||||
self.actionBar.origin = {0., self.ownerView.height};
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
self.state = State::Top;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
|
||||
{
|
||||
if (decelerate)
|
||||
return;
|
||||
|
||||
auto const actualOffset = scrollView.contentOffset.y;
|
||||
auto const openOffset = self.isPortrait ? self.portraitOpenContentOffset : self.landscapeOpenContentOffset;
|
||||
if (actualOffset < self.expandedContentOffset + 30)
|
||||
{
|
||||
self.state = State::Bottom;
|
||||
animate(^{
|
||||
[scrollView setContentOffset:{0, self.expandedContentOffset} animated:YES];
|
||||
});
|
||||
}
|
||||
else if (actualOffset < openOffset)
|
||||
{
|
||||
self.state = self.direction == ScrollDirection::Up ? State::Top : State::Bottom;
|
||||
animate(^{
|
||||
[scrollView setContentOffset:{0, self.direction == ScrollDirection::Up ? openOffset : self.expandedContentOffset}
|
||||
animated:YES];
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
self.state = State::Top;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate & UITableViewDataSource
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
|
||||
{
|
||||
if (!self.data)
|
||||
return 0;
|
||||
return self.data.sections.size();
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
using namespace place_page;
|
||||
|
||||
switch (self.data.sections[section])
|
||||
{
|
||||
case Sections::Preview:
|
||||
case Sections::Bookmark: return 1;
|
||||
case Sections::Metainfo: return self.data.metainfoRows.size();
|
||||
case Sections::Buttons: return self.data.buttonsRows.size();
|
||||
}
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
using namespace place_page;
|
||||
|
||||
switch (self.data.sections[indexPath.section])
|
||||
{
|
||||
case Sections::Preview:
|
||||
{
|
||||
if (!self.ppPreviewCell)
|
||||
self.ppPreviewCell = [tableView dequeueReusableCellWithIdentifier:[MWMPlacePagePreviewCell className]];
|
||||
|
||||
[self.ppPreviewCell configure:self.data updateLayoutDelegate:self dataSource:self.dataSource];
|
||||
[self.ppPreviewCell setDownloaderViewHidden:!self.isDownloaderViewShown animated:NO];
|
||||
|
||||
return self.ppPreviewCell;
|
||||
}
|
||||
case Sections::Bookmark:
|
||||
{
|
||||
MWMBookmarkCell * c = [tableView dequeueReusableCellWithIdentifier:kBookmarkCells[0]];
|
||||
[c configureWithText:self.data.bookmarkDescription
|
||||
updateCellDelegate:self
|
||||
editBookmarkDelegate:self.delegate
|
||||
isHTML:self.data.isHTMLDescription];
|
||||
return c;
|
||||
}
|
||||
case Sections::Metainfo:
|
||||
{
|
||||
auto const row = self.data.metainfoRows[indexPath.row];
|
||||
auto cellName = kMetaInfoCells[static_cast<size_t>(row)];
|
||||
UITableViewCell * c = [tableView dequeueReusableCellWithIdentifier:cellName];
|
||||
|
||||
switch (row)
|
||||
{
|
||||
case MetainfoRows::OpeningHours:
|
||||
[static_cast<MWMOpeningHoursCell *>(c) configureWithOpeningHours:[self.data stringForRow:row]
|
||||
updateLayoutDelegate:self
|
||||
isClosedNow:self.data.schedule == OpeningHours::Closed];
|
||||
break;
|
||||
case MetainfoRows::Phone:
|
||||
case MetainfoRows::Address:
|
||||
case MetainfoRows::Website:
|
||||
case MetainfoRows::Email:
|
||||
case MetainfoRows::Cuisine:
|
||||
case MetainfoRows::Operator:
|
||||
case MetainfoRows::Internet:
|
||||
case MetainfoRows::Coordinate:
|
||||
[static_cast<MWMPlacePageInfoCell *>(c) configWithRow:row data:self.data];
|
||||
break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
case Sections::Buttons:
|
||||
{
|
||||
MWMPlacePageButtonCell * c = [tableView dequeueReusableCellWithIdentifier:kButtonsCells[0]];
|
||||
auto const row = self.data.buttonsRows[indexPath.row];
|
||||
[c configForRow:row withDelegate:self.delegate];
|
||||
if (row != ButtonsRows::HotelDescription)
|
||||
[c setEnabled:self.isPlacePageButtonsEnabled];
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - MWMPlacePageCellUpdateProtocol
|
||||
|
||||
- (void)updateCellWithForceReposition:(BOOL)isForceReposition
|
||||
{
|
||||
auto const update = isForceReposition ? @selector(updateWithExpand) : @selector(update);
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:update object:nil];
|
||||
[self performSelector:update withObject:nil afterDelay:0.5];
|
||||
}
|
||||
|
||||
- (void)update
|
||||
{
|
||||
auto tableView = self.placePageView.tableView;
|
||||
[tableView beginUpdates];
|
||||
[tableView endUpdates];
|
||||
}
|
||||
|
||||
- (void)updateWithExpand
|
||||
{
|
||||
[self update];
|
||||
[self expand];
|
||||
}
|
||||
|
||||
#pragma mark - MWMPlacePageViewUpdateProtocol
|
||||
|
||||
- (void)updateWithHeight:(CGFloat)height
|
||||
{
|
||||
auto const & size = self.ownerView.size;
|
||||
self.scrollView.contentSize = {size.width, size.height + height};
|
||||
}
|
||||
|
||||
@end
|
5
iphone/Maps/Classes/MWMPlacePageManager.h
Normal file
5
iphone/Maps/Classes/MWMPlacePageManager.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#import "MWMPlacePageProtocol.h"
|
||||
|
||||
@interface MWMPlacePageManager : NSObject <MWMPlacePageProtocol>
|
||||
|
||||
@end
|
335
iphone/Maps/Classes/MWMPlacePageManager.mm
Normal file
335
iphone/Maps/Classes/MWMPlacePageManager.mm
Normal file
|
@ -0,0 +1,335 @@
|
|||
#import "MapViewController.h"
|
||||
#import "MWMActivityViewController.h"
|
||||
#import "MWMAPIBar.h"
|
||||
#import "MWMCircularProgress.h"
|
||||
#import "MWMPlacePageManager.h"
|
||||
#import "MWMViewController.h"
|
||||
#import "MWMPlacePageLayout.h"
|
||||
#import "MWMPlacePageData.h"
|
||||
#import "MWMFrameworkListener.h"
|
||||
#import "MWMFrameworkObservers.h"
|
||||
#import "MWMLocationManager.h"
|
||||
#import "MWMRouter.h"
|
||||
#import "MWMStorage.h"
|
||||
#import "MWMEditBookmarkController.h"
|
||||
#import "Statistics.h"
|
||||
#import <Pushwoosh/PushNotificationManager.h>
|
||||
|
||||
#include "geometry/distance_on_sphere.hpp"
|
||||
|
||||
#include "platform/measurement_utils.hpp"
|
||||
|
||||
@interface MWMPlacePageManager() <MWMFrameworkStorageObserver, MWMPlacePageLayoutDelegate,
|
||||
MWMPlacePageLayoutDataSource, MWMLocationObserver>
|
||||
|
||||
@property(weak, nonatomic) MWMViewController * ownerViewController;
|
||||
@property(nonatomic) MWMPlacePageEntity * entity;
|
||||
|
||||
@property(nonatomic) MWMPlacePageLayout * layout;
|
||||
@property(nonatomic) MWMPlacePageData * data;
|
||||
|
||||
@property(nonatomic) storage::NodeStatus currentDownloaderStatus;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MWMPlacePageManager
|
||||
|
||||
- (instancetype)initWithViewController:(MWMViewController *)viewController
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
_ownerViewController = viewController;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)showPlacePage:(place_page::Info const &)info
|
||||
{
|
||||
self.currentDownloaderStatus = storage::NodeStatus::Undefined;
|
||||
[MWMFrameworkListener addObserver:self];
|
||||
|
||||
self.data = [[MWMPlacePageData alloc] initWithPlacePageInfo:info];
|
||||
[self.layout showWithData:self.data];
|
||||
|
||||
// Call for the first time to produce changes
|
||||
[self processCountryEvent:self.data.countryId];
|
||||
|
||||
if (![MWMLocationManager lastHeading])
|
||||
return;
|
||||
|
||||
[MWMLocationManager addObserver:self];
|
||||
[self.layout setDistanceToObject:self.distanceToObject];
|
||||
}
|
||||
|
||||
- (void)closePlacePage
|
||||
{
|
||||
[_layout close];
|
||||
[MWMLocationManager removeObserver:self];
|
||||
[MWMFrameworkListener removeObserver:self];
|
||||
}
|
||||
|
||||
#pragma mark - MWMPlacePageLayoutDataSource
|
||||
|
||||
- (void)downloadSelectedArea
|
||||
{
|
||||
auto const & countryId = self.data.countryId;
|
||||
NodeAttrs nodeAttrs;
|
||||
GetFramework().GetStorage().GetNodeAttrs(countryId, nodeAttrs);
|
||||
MWMAlertViewController * avc = [MapViewController controller].alertController;
|
||||
switch (nodeAttrs.m_status)
|
||||
{
|
||||
case NodeStatus::NotDownloaded:
|
||||
case NodeStatus::Partly:
|
||||
[MWMStorage downloadNode:countryId alertController:avc onSuccess:nil];
|
||||
break;
|
||||
case NodeStatus::Undefined:
|
||||
case NodeStatus::Error: [MWMStorage retryDownloadNode:countryId]; break;
|
||||
case NodeStatus::OnDiskOutOfDate: [MWMStorage updateNode:countryId alertController:avc]; break;
|
||||
case NodeStatus::Downloading:
|
||||
case NodeStatus::InQueue: [MWMStorage cancelDownloadNode:countryId]; break;
|
||||
case NodeStatus::OnDisk: break;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)distanceToObject
|
||||
{
|
||||
CLLocation * lastLocation = [MWMLocationManager lastLocation];
|
||||
if (!lastLocation)
|
||||
return @"";
|
||||
string distance;
|
||||
CLLocationCoordinate2D const coord = lastLocation.coordinate;
|
||||
ms::LatLon const target = self.data.latLon;
|
||||
measurement_utils::FormatDistance(
|
||||
ms::DistanceOnEarth(coord.latitude, coord.longitude, target.lat, target.lon), distance);
|
||||
return @(distance.c_str());
|
||||
}
|
||||
|
||||
#pragma mark - MWMFrameworkStorageObserver
|
||||
|
||||
- (void)processCountryEvent:(TCountryId const &)countryId
|
||||
{
|
||||
if (countryId == kInvalidCountryId)
|
||||
{
|
||||
[_layout processDownloaderEventWithStatus:storage::NodeStatus::Undefined progress:0];
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.data.countryId != countryId)
|
||||
return;
|
||||
|
||||
NodeStatuses statuses;
|
||||
GetFramework().GetStorage().GetNodeStatuses(countryId, statuses);
|
||||
|
||||
auto const status = statuses.m_status;
|
||||
if (status == self.currentDownloaderStatus)
|
||||
return;
|
||||
|
||||
self.currentDownloaderStatus = status;
|
||||
[_layout processDownloaderEventWithStatus:status progress:0];
|
||||
}
|
||||
|
||||
- (void)processCountry:(TCountryId const &)countryId progress:(MapFilesDownloader::TProgress const &)progress
|
||||
{
|
||||
if (countryId == kInvalidCountryId || self.data.countryId != countryId)
|
||||
return;
|
||||
|
||||
[_layout processDownloaderEventWithStatus:storage::NodeStatus::Downloading
|
||||
progress:static_cast<CGFloat>(progress.first) / progress.second];
|
||||
}
|
||||
|
||||
#pragma mark - MWMPlacePageLayout
|
||||
|
||||
- (MWMPlacePageLayout *)layout
|
||||
{
|
||||
if (!_layout)
|
||||
{
|
||||
_layout = [[MWMPlacePageLayout alloc] initWithOwnerView:self.ownerViewController.view
|
||||
delegate:self
|
||||
dataSource:self];
|
||||
}
|
||||
|
||||
return _layout;
|
||||
}
|
||||
|
||||
- (void)onTopBoundChanged:(CGFloat)bound
|
||||
{
|
||||
[[MWMMapViewControlsManager manager] dragPlacePage:{{0, self.ownerViewController.view.height - bound}, {}}];
|
||||
}
|
||||
|
||||
- (void)shouldDestroyLayout
|
||||
{
|
||||
self.layout = nil;
|
||||
GetFramework().DeactivateMapSelection(false);
|
||||
}
|
||||
|
||||
#pragma mark - MWMLocationObserver
|
||||
|
||||
- (void)onHeadingUpdate:(location::CompassInfo const &)info
|
||||
{
|
||||
CLLocation * lastLocation = [MWMLocationManager lastLocation];
|
||||
if (!lastLocation)
|
||||
return;
|
||||
|
||||
CGFloat const angle = ang::AngleTo(lastLocation.mercator, self.data.mercator) + info.m_bearing;
|
||||
[_layout rotateDirectionArrowToAngle:angle];
|
||||
}
|
||||
|
||||
- (void)onLocationUpdate:(location::GpsInfo const &)locationInfo
|
||||
{
|
||||
[_layout setDistanceToObject:self.distanceToObject];
|
||||
}
|
||||
|
||||
- (void)mwm_refreshUI
|
||||
{
|
||||
[_layout mwm_refreshUI];
|
||||
}
|
||||
|
||||
- (void)dismissPlacePage
|
||||
{
|
||||
[self closePlacePage];
|
||||
}
|
||||
|
||||
- (void)hidePlacePage
|
||||
{
|
||||
[self closePlacePage];
|
||||
}
|
||||
|
||||
- (void)routeFrom
|
||||
{
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatBuildRoute)
|
||||
withParameters:@{kStatValue : kStatSource}];
|
||||
[[MWMRouter router] buildFromPoint:self.target bestRouter:YES];
|
||||
[self closePlacePage];
|
||||
}
|
||||
|
||||
- (void)routeTo
|
||||
{
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatBuildRoute)
|
||||
withParameters:@{kStatValue : kStatDestination}];
|
||||
[[MWMRouter router] buildToPoint:self.target bestRouter:YES];
|
||||
[self closePlacePage];
|
||||
}
|
||||
|
||||
- (MWMRoutePoint)target
|
||||
{
|
||||
NSString * name = nil;
|
||||
if (self.data.title.length > 0)
|
||||
name = self.data.title;
|
||||
else if (self.data.address.length > 0)
|
||||
name = self.data.address;
|
||||
else if (self.data.subtitle.length > 0)
|
||||
name = self.data.subtitle;
|
||||
else if (self.data.isBookmark)
|
||||
name = self.data.externalTitle;
|
||||
else
|
||||
name = L(@"placepage_unknown_place");
|
||||
|
||||
m2::PointD const & org = self.data.mercator;
|
||||
return self.data.isMyPosition ? MWMRoutePoint(org) : MWMRoutePoint(org, name);
|
||||
}
|
||||
|
||||
- (void)share
|
||||
{
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatShare)];
|
||||
MWMActivityViewController * shareVC =
|
||||
[MWMActivityViewController shareControllerForPlacePageObject:static_cast<id<MWMPlacePageObject>>(self.data)];
|
||||
[shareVC presentInParentViewController:self.ownerViewController
|
||||
anchorView:self.layout.shareAnchor];
|
||||
}
|
||||
|
||||
- (void)editPlace
|
||||
{
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatEdit)];
|
||||
[[PushNotificationManager pushManager] setTags:@{ @"editor_edit_discovered" : @YES }];
|
||||
[(MapViewController *)self.ownerViewController openEditor];
|
||||
}
|
||||
|
||||
- (void)addBusiness
|
||||
{
|
||||
[Statistics logEvent:kStatEditorAddClick withParameters:@{kStatValue : kStatPlacePage}];
|
||||
[[MWMMapViewControlsManager manager] addPlace:YES hasPoint:NO point:m2::PointD()];
|
||||
}
|
||||
|
||||
- (void)addPlace
|
||||
{
|
||||
[Statistics logEvent:kStatEditorAddClick
|
||||
withParameters:@{kStatValue : kStatPlacePageNonBuilding}];
|
||||
[[MWMMapViewControlsManager manager] addPlace:NO hasPoint:YES point:self.data.mercator];
|
||||
}
|
||||
|
||||
|
||||
- (void)addBookmark
|
||||
{
|
||||
[self.data updateBookmarkStatus:YES];
|
||||
[self.layout reloadBookmarkSection:YES];
|
||||
}
|
||||
|
||||
- (void)removeBookmark
|
||||
{
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatBookmarks)
|
||||
withParameters:@{kStatValue : kStatRemove}];
|
||||
[self.data updateBookmarkStatus:NO];
|
||||
[self.layout reloadBookmarkSection:NO];
|
||||
}
|
||||
|
||||
- (void)editBookmark
|
||||
{
|
||||
[[MapViewController controller] openBookmarkEditorWithData:self.data];
|
||||
}
|
||||
|
||||
- (void)book:(BOOL)isDescription
|
||||
{
|
||||
NSMutableDictionary * stat = [@{ kStatProvider : kStatBooking } mutableCopy];
|
||||
MWMPlacePageData * data = self.data;
|
||||
auto const latLon = data.latLon;
|
||||
stat[kStatHotel] = data.hotelId;
|
||||
stat[kStatHotelLat] = @(latLon.lat);
|
||||
stat[kStatHotelLon] = @(latLon.lon);
|
||||
[Statistics logEvent:isDescription ? kPlacePageHotelDetails : kPlacePageHotelBook
|
||||
withParameters:stat
|
||||
atLocation:[MWMLocationManager lastLocation]];
|
||||
|
||||
UIViewController * vc = static_cast<UIViewController *>([MapViewController controller]);
|
||||
NSURL * url = isDescription ? self.data.bookingDescriptionURL : self.data.bookingURL;
|
||||
NSAssert(url, @"Booking url can't be nil!");
|
||||
[vc openUrl:url];
|
||||
}
|
||||
|
||||
- (void)call
|
||||
{
|
||||
NSAssert(self.data.phoneNumber, @"Phone number can't be nil!");
|
||||
NSString * phoneNumber = [[@"telprompt:" stringByAppendingString:self.data.phoneNumber]
|
||||
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:phoneNumber]];
|
||||
}
|
||||
|
||||
- (void)apiBack
|
||||
{
|
||||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatAPI)];
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.data.apiURL]];
|
||||
[[MapViewController controller].apiBar back];
|
||||
}
|
||||
|
||||
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
|
||||
{
|
||||
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
|
||||
[self->_layout layoutWithSize:size];
|
||||
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { }];
|
||||
}
|
||||
|
||||
#pragma mark - MWMFeatureHolder
|
||||
|
||||
- (FeatureID const &)featureId
|
||||
{
|
||||
return self.data.featureId;
|
||||
}
|
||||
|
||||
#pragma mark - Deprecated
|
||||
|
||||
@synthesize leftBound = _leftBound;
|
||||
@synthesize topBound = _topBound;
|
||||
- (void)setTopBound:(CGFloat)topBound {_topBound = 0;}
|
||||
- (void)setLeftBound:(CGFloat)leftBound {_leftBound = 0;}
|
||||
- (void)addSubviews:(NSArray *)views withNavigationController:(UINavigationController *)controller {}
|
||||
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {}
|
||||
|
||||
@end
|
24
iphone/Maps/Classes/MWMPlacePagePreviewCell.h
Normal file
24
iphone/Maps/Classes/MWMPlacePagePreviewCell.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#import "MWMTableViewCell.h"
|
||||
|
||||
@class MWMPlacePageData;
|
||||
@class MWMCircularProgress;
|
||||
|
||||
@protocol MWMPlacePageCellUpdateProtocol;
|
||||
@protocol MWMPlacePageLayoutDataSource;
|
||||
|
||||
@interface MWMPlacePagePreviewCell : MWMTableViewCell
|
||||
|
||||
- (void)setDistanceToObject:(NSString *)distance;
|
||||
- (void)rotateDirectionArrowToAngle:(CGFloat)angle;
|
||||
|
||||
- (void)setDownloaderViewHidden:(BOOL)isHidden animated:(BOOL)isAnimated;
|
||||
- (void)setDownloadingProgress:(CGFloat)progress;
|
||||
|
||||
- (void)configure:(MWMPlacePageData *)data
|
||||
updateLayoutDelegate:(id<MWMPlacePageCellUpdateProtocol>)delegate
|
||||
dataSource:(id<MWMPlacePageLayoutDataSource>)dataSource;
|
||||
|
||||
|
||||
- (MWMCircularProgress *)mapDownloadProgress;
|
||||
|
||||
@end
|
426
iphone/Maps/Classes/MWMPlacePagePreviewCell.mm
Normal file
426
iphone/Maps/Classes/MWMPlacePagePreviewCell.mm
Normal file
|
@ -0,0 +1,426 @@
|
|||
#import "Common.h"
|
||||
#import "MWMDirectionView.h"
|
||||
#import "MWMPlacePageCellUpdateProtocol.h"
|
||||
#import "MWMPlacePageData.h"
|
||||
#import "MWMPlacePageLayout.h"
|
||||
#import "MWMPlacePagePreviewCell.h"
|
||||
#import "MWMCircularProgress.h"
|
||||
#import "UIColor+MapsmeColor.h"
|
||||
|
||||
#include "std/array.hpp"
|
||||
#include "std/vector.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
array<NSString *, 6> kPPPClasses = {{@"_MWMPPPTitle",
|
||||
@"_MWMPPPExternalTitle",
|
||||
@"_MWMPPPSubtitle",
|
||||
@"_MWMPPPSchedule",
|
||||
@"_MWMPPPBooking",
|
||||
@"_MWMPPPAddress"}};
|
||||
|
||||
enum class Labels
|
||||
{
|
||||
Title,
|
||||
ExternalTitle,
|
||||
Subtitle,
|
||||
Schedule,
|
||||
Booking,
|
||||
Address
|
||||
};
|
||||
|
||||
void * kContext = &kContext;
|
||||
NSString * const kTableViewContentSizeKeyPath = @"contentSize";
|
||||
CGFloat const kDefaultTableViewLeading = 16;
|
||||
CGFloat const kCompressedTableViewLeading = 56;
|
||||
|
||||
} // namespace
|
||||
|
||||
#pragma mark - Base
|
||||
|
||||
// Base class for avoiding copy-paste in inheriting cells.
|
||||
@interface _MWMPPPCellBase : MWMTableViewCell
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * distance;
|
||||
@property(weak, nonatomic) IBOutlet UIImageView * compass;
|
||||
@property(weak, nonatomic) IBOutlet UIView * distanceView;
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * trailing;
|
||||
@property(copy, nonatomic) TMWMVoidBlock tapOnDistance;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMPPPCellBase
|
||||
|
||||
- (IBAction)tap
|
||||
{
|
||||
if (self.tapOnDistance)
|
||||
self.tapOnDistance();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Title
|
||||
|
||||
@interface _MWMPPPTitle : _MWMPPPCellBase
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * title;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMPPPTitle
|
||||
@end
|
||||
|
||||
#pragma mark - External Title
|
||||
|
||||
@interface _MWMPPPExternalTitle : _MWMPPPCellBase
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * externalTitle;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMPPPExternalTitle
|
||||
@end
|
||||
|
||||
#pragma mark - Subtitle
|
||||
|
||||
@interface _MWMPPPSubtitle : _MWMPPPCellBase
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * subtitle;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMPPPSubtitle
|
||||
@end
|
||||
|
||||
#pragma mark - Schedule
|
||||
|
||||
@interface _MWMPPPSchedule : _MWMPPPCellBase
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * schedule;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMPPPSchedule
|
||||
@end
|
||||
|
||||
#pragma mark - Booking
|
||||
|
||||
@interface _MWMPPPBooking : MWMTableViewCell
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * rating;
|
||||
@property(weak, nonatomic) IBOutlet UILabel * pricing;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMPPPBooking
|
||||
@end
|
||||
|
||||
#pragma mark - Address
|
||||
|
||||
@interface _MWMPPPAddress : _MWMPPPCellBase
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UILabel * address;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _MWMPPPAddress
|
||||
@end
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
@interface MWMPlacePagePreviewCell () <UITableViewDelegate, UITableViewDataSource, MWMCircularProgressProtocol>
|
||||
{
|
||||
vector<Labels> m_cells;
|
||||
}
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UITableView * tableView;
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * tableViewHeight;
|
||||
@property(weak, nonatomic) NSLayoutConstraint * trailing;
|
||||
@property(weak, nonatomic) UIView * distanceView;
|
||||
|
||||
@property(weak, nonatomic) IBOutlet UIView * downloaderParentView;
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint * tableViewLeading;
|
||||
|
||||
@property(nonatomic) MWMCircularProgress * mapDownloadProgress;
|
||||
|
||||
@property(nonatomic) BOOL isDirectionViewAvailable;
|
||||
|
||||
@property(weak, nonatomic) MWMPlacePageData * data;
|
||||
@property(weak, nonatomic) id<MWMPlacePageCellUpdateProtocol> delegate;
|
||||
@property(weak, nonatomic) id<MWMPlacePageLayoutDataSource> dataSource;
|
||||
|
||||
@property(copy, nonatomic) NSString * distance;
|
||||
@property(weak, nonatomic) UIImageView * compass;
|
||||
@property(nonatomic) CGFloat currentContentHeight;
|
||||
|
||||
@property(nonatomic) MWMDirectionView * directionView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MWMPlacePagePreviewCell
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
for (auto const s : kPPPClasses)
|
||||
[self.tableView registerNib:[UINib nibWithNibName:s bundle:nil] forCellReuseIdentifier:s];
|
||||
|
||||
self.tableView.estimatedRowHeight = 20;
|
||||
self.tableView.rowHeight = UITableViewAutomaticDimension;
|
||||
[self registerObserver];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self unregisterObserver];
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context
|
||||
{
|
||||
if (context == kContext)
|
||||
{
|
||||
NSValue * s = change[@"new"];
|
||||
CGFloat const height = s.CGSizeValue.height;
|
||||
if (abs(height - self.currentContentHeight) > 0.5)
|
||||
{
|
||||
self.currentContentHeight = height;
|
||||
self.tableViewHeight.constant = height;
|
||||
[self setNeedsLayout];
|
||||
[self.delegate updateCellWithForceReposition:YES];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
||||
}
|
||||
|
||||
- (MWMDirectionView *)directionView
|
||||
{
|
||||
if (!_directionView)
|
||||
_directionView = [[MWMDirectionView alloc] initWithManager:nil];
|
||||
return _directionView;
|
||||
}
|
||||
|
||||
- (void)setIsDirectionViewAvailable:(BOOL)isDirectionViewAvailable
|
||||
{
|
||||
if (_isDirectionViewAvailable == isDirectionViewAvailable)
|
||||
return;
|
||||
_isDirectionViewAvailable = isDirectionViewAvailable;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)rotateDirectionArrowToAngle:(CGFloat)angle
|
||||
{
|
||||
self.compass.layer.transform = CATransform3DMakeRotation(M_PI_2 - angle, 0, 0, 1);
|
||||
self.directionView.directionArrow.layer.transform = CATransform3DMakeRotation(M_PI_2 - angle, 0, 0, 1);
|
||||
}
|
||||
|
||||
- (void)setDistanceToObject:(NSString *)distance
|
||||
{
|
||||
if (!distance.length)
|
||||
{
|
||||
self.isDirectionViewAvailable = NO;
|
||||
[self setNeedsLayout];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([self.distance isEqualToString:distance])
|
||||
return;
|
||||
|
||||
self.distance = distance;
|
||||
self.directionView.distanceLabel.text = distance;
|
||||
self.isDirectionViewAvailable = YES;
|
||||
}
|
||||
|
||||
- (void)unregisterObserver
|
||||
{
|
||||
[self.tableView removeObserver:self forKeyPath:kTableViewContentSizeKeyPath context:kContext];
|
||||
}
|
||||
|
||||
- (void)registerObserver
|
||||
{
|
||||
[self.tableView addObserver:self forKeyPath:kTableViewContentSizeKeyPath options:NSKeyValueObservingOptionNew context:kContext];
|
||||
}
|
||||
|
||||
- (void)setDownloadingProgress:(CGFloat)progress
|
||||
{
|
||||
self.mapDownloadProgress.progress = progress;
|
||||
}
|
||||
|
||||
- (void)setDownloaderViewHidden:(BOOL)isHidden animated:(BOOL)isAnimated
|
||||
{
|
||||
self.downloaderParentView.hidden = isHidden;
|
||||
self.tableViewLeading.constant = isHidden ? kDefaultTableViewLeading : kCompressedTableViewLeading;
|
||||
[self setNeedsLayout];
|
||||
|
||||
if (!isHidden)
|
||||
self.mapDownloadProgress.state = MWMCircularProgressStateNormal;
|
||||
|
||||
if (!isAnimated)
|
||||
return;
|
||||
|
||||
[UIView animateWithDuration:kDefaultAnimationDuration animations:^{
|
||||
[self layoutIfNeeded];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)configure:(MWMPlacePageData *)data
|
||||
updateLayoutDelegate:(id<MWMPlacePageCellUpdateProtocol>)delegate
|
||||
dataSource:(id<MWMPlacePageLayoutDataSource>)dataSource
|
||||
{
|
||||
self.data = data;
|
||||
self.delegate = delegate;
|
||||
self.dataSource = dataSource;
|
||||
[self setDistanceToObject:dataSource.distanceToObject];
|
||||
|
||||
m_cells.clear();
|
||||
|
||||
if (data.title.length)
|
||||
m_cells.push_back(Labels::Title);
|
||||
|
||||
if (data.externalTitle.length)
|
||||
m_cells.push_back(Labels::ExternalTitle);
|
||||
|
||||
if (data.subtitle.length)
|
||||
m_cells.push_back(Labels::Subtitle);
|
||||
|
||||
if (data.schedule != place_page::OpeningHours::Unknown)
|
||||
m_cells.push_back(Labels::Schedule);
|
||||
|
||||
if (data.bookingRating.length)
|
||||
m_cells.push_back(Labels::Booking);
|
||||
|
||||
if (data.address.length)
|
||||
m_cells.push_back(Labels::Address);
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return m_cells.size();
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
auto data = self.data;
|
||||
_MWMPPPCellBase * c = nil;
|
||||
BOOL const isNeedToShowDistance = self.isDirectionViewAvailable && (indexPath.row == m_cells.size() - 1);
|
||||
|
||||
switch (m_cells[indexPath.row])
|
||||
{
|
||||
case Labels::Title:
|
||||
{
|
||||
c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPTitle className]];
|
||||
static_cast<_MWMPPPTitle *>(c).title.text = data.title;
|
||||
break;
|
||||
}
|
||||
case Labels::ExternalTitle:
|
||||
{
|
||||
c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPExternalTitle className]];
|
||||
static_cast<_MWMPPPExternalTitle *>(c).externalTitle.text = data.externalTitle;
|
||||
break;
|
||||
}
|
||||
case Labels::Subtitle:
|
||||
{
|
||||
c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPSubtitle className]];
|
||||
static_cast<_MWMPPPSubtitle *>(c).subtitle.text = data.subtitle;
|
||||
break;
|
||||
}
|
||||
case Labels::Schedule:
|
||||
{
|
||||
c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPSchedule className]];
|
||||
auto castedCell = static_cast<_MWMPPPSchedule *>(c);
|
||||
switch(data.schedule)
|
||||
{
|
||||
case place_page::OpeningHours::AllDay:
|
||||
castedCell.schedule.text = L(@"twentyfour_seven");
|
||||
castedCell.schedule.textColor = [UIColor blackSecondaryText];
|
||||
break;
|
||||
case place_page::OpeningHours::Open:
|
||||
castedCell.schedule.text = L(@"editor_time_open");
|
||||
castedCell.schedule.textColor = [UIColor blackSecondaryText];
|
||||
break;
|
||||
case place_page::OpeningHours::Closed:
|
||||
castedCell.schedule.text = L(@"closed_now");
|
||||
castedCell.schedule.textColor = [UIColor red];
|
||||
break;
|
||||
case place_page::OpeningHours::Unknown:
|
||||
NSAssert(false, @"Incorrect schedule!");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Labels::Booking:
|
||||
{
|
||||
_MWMPPPBooking * c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPBooking className]];
|
||||
c.rating.text = data.bookingRating;
|
||||
c.pricing.text = data.bookingApproximatePricing;
|
||||
[data assignOnlinePriceToLabel:c.pricing];
|
||||
return c;
|
||||
}
|
||||
case Labels::Address:
|
||||
{
|
||||
c = [tableView dequeueReusableCellWithIdentifier:[_MWMPPPAddress className]];
|
||||
static_cast<_MWMPPPAddress *>(c).address.text = data.address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isNeedToShowDistance)
|
||||
[self showDistanceOnCell:c];
|
||||
else
|
||||
[self hideDistanceOnCell:c];
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
- (void)showDistanceOnCell:(_MWMPPPCellBase *)cell
|
||||
{
|
||||
cell.trailing.priority = UILayoutPriorityDefaultLow;
|
||||
cell.distance.text = self.distance;
|
||||
cell.tapOnDistance = ^{ [self.directionView show]; };
|
||||
[cell.contentView setNeedsLayout];
|
||||
self.compass = cell.compass;
|
||||
self.trailing = cell.trailing;
|
||||
self.distanceView = cell.distanceView;
|
||||
cell.distanceView.hidden = NO;
|
||||
}
|
||||
|
||||
- (void)hideDistanceOnCell:(_MWMPPPCellBase *)cell
|
||||
{
|
||||
cell.trailing.priority = UILayoutPriorityDefaultHigh;
|
||||
[cell.contentView setNeedsLayout];
|
||||
cell.distanceView.hidden = YES;
|
||||
}
|
||||
|
||||
#pragma mark - MWMCircularProgressProtocol
|
||||
|
||||
- (void)progressButtonPressed:(MWMCircularProgress *)progress
|
||||
{
|
||||
[self.dataSource downloadSelectedArea];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (MWMCircularProgress *)mapDownloadProgress
|
||||
{
|
||||
if (!_mapDownloadProgress)
|
||||
{
|
||||
_mapDownloadProgress =
|
||||
[MWMCircularProgress downloaderProgressForParentView:self.downloaderParentView];
|
||||
_mapDownloadProgress.delegate = self;
|
||||
|
||||
MWMCircularProgressStateVec const affectedStates = {MWMCircularProgressStateNormal,
|
||||
MWMCircularProgressStateSelected};
|
||||
|
||||
[_mapDownloadProgress setImage:[UIImage imageNamed:@"ic_download"] forStates:affectedStates];
|
||||
[_mapDownloadProgress setColoring:MWMButtonColoringBlue forStates:affectedStates];
|
||||
}
|
||||
return _mapDownloadProgress;
|
||||
}
|
||||
|
||||
@end
|
58
iphone/Maps/Classes/MWMPlacePageProtocol.h
Normal file
58
iphone/Maps/Classes/MWMPlacePageProtocol.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
#import "MWMMapViewControlsManager.h"
|
||||
|
||||
#include "Framework.h"
|
||||
|
||||
@class MWMPlacePageEntity, MWMViewController;
|
||||
|
||||
@protocol MWMActionBarProtocol <NSObject>
|
||||
|
||||
- (void)routeFrom;
|
||||
- (void)routeTo;
|
||||
|
||||
- (void)share;
|
||||
|
||||
- (void)addBookmark;
|
||||
- (void)removeBookmark;
|
||||
|
||||
- (void)call;
|
||||
- (void)book:(BOOL)isDecription;
|
||||
|
||||
- (void)apiBack;
|
||||
|
||||
@end
|
||||
|
||||
@protocol MWMPlacePageButtonsProtocol <NSObject>
|
||||
|
||||
- (void)editPlace;
|
||||
- (void)addPlace;
|
||||
- (void)addBusiness;
|
||||
- (void)book:(BOOL)isDescription;
|
||||
- (void)editBookmark;
|
||||
|
||||
@end
|
||||
|
||||
struct FeatureID;
|
||||
|
||||
@protocol MWMFeatureHolder <NSObject>
|
||||
|
||||
- (FeatureID const &)featureId;
|
||||
|
||||
@end
|
||||
|
||||
@protocol MWMPlacePageProtocol <MWMActionBarProtocol, MWMPlacePageButtonsProtocol, MWMFeatureHolder>
|
||||
|
||||
@property(weak, nonatomic, readonly) MWMViewController * ownerViewController;
|
||||
@property(nonatomic) CGFloat topBound;
|
||||
@property(nonatomic) CGFloat leftBound;
|
||||
|
||||
- (instancetype)initWithViewController:(MWMViewController *)viewController;
|
||||
- (void)showPlacePage:(place_page::Info const &)info;
|
||||
- (void)mwm_refreshUI;
|
||||
- (void)dismissPlacePage;
|
||||
- (void)hidePlacePage;
|
||||
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation;
|
||||
- (void)viewWillTransitionToSize:(CGSize)size
|
||||
withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator;
|
||||
- (void)addSubviews:(NSArray *)views withNavigationController:(UINavigationController *)controller;
|
||||
|
||||
@end
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
#include "Framework.h"
|
||||
|
||||
#include "MWMPlacePageProtocol.h"
|
||||
|
||||
@class MWMPlacePageEntity, MWMPlacePageNavigationBar, MWMViewController;
|
||||
|
||||
@interface MWMPlacePageViewManager : NSObject
|
||||
@interface MWMPlacePageViewManager : NSObject <MWMPlacePageProtocol>
|
||||
|
||||
@property(weak, nonatomic, readonly) MWMViewController * ownerViewController;
|
||||
@property(nonatomic, readonly) MWMPlacePageEntity * entity;
|
||||
@property(nonatomic) MWMPlacePageNavigationBar * iPhoneNavigationBar;
|
||||
@property(nonatomic) CGFloat topBound;
|
||||
@property(nonatomic) CGFloat leftBound;
|
||||
@property(nonatomic, readonly) BOOL isDirectionViewShown;
|
||||
|
||||
- (instancetype)initWithViewController:(MWMViewController *)viewController;
|
||||
- (void)showPlacePage:(place_page::Info const &)info;
|
||||
|
@ -37,7 +37,6 @@
|
|||
- (void)reloadBookmark;
|
||||
- (void)dragPlacePage:(CGRect)frame;
|
||||
- (void)showDirectionViewWithTitle:(NSString *)title type:(NSString *)type;
|
||||
- (void)hideDirectionView;
|
||||
- (void)addSubviews:(NSArray *)views withNavigationController:(UINavigationController *)controller;
|
||||
- (void)changeHeight:(CGFloat)height;
|
||||
|
||||
|
|
|
@ -70,6 +70,11 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
[self configPlacePage];
|
||||
}
|
||||
|
||||
- (FeatureID const &)featureId
|
||||
{
|
||||
return self.entity.featureID;
|
||||
}
|
||||
|
||||
#pragma mark - Layout
|
||||
|
||||
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
|
||||
|
@ -211,7 +216,7 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
[Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"ppShare"];
|
||||
MWMPlacePageEntity * entity = self.entity;
|
||||
MWMActivityViewController * shareVC =
|
||||
[MWMActivityViewController shareControllerForPlacePageObject:entity];
|
||||
[MWMActivityViewController shareControllerForPlacePageObject:static_cast<id<MWMPlacePageObject>>(entity)];
|
||||
[shareVC presentInParentViewController:self.ownerViewController
|
||||
anchorView:self.placePage.actionBar.shareAnchor];
|
||||
}
|
||||
|
@ -220,7 +225,7 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
{
|
||||
NSMutableDictionary * stat = [@{ kStatProvider : kStatBooking } mutableCopy];
|
||||
MWMPlacePageEntity * en = self.entity;
|
||||
auto const latLon = en.latlon;
|
||||
auto const latLon = en.latLon;
|
||||
stat[kStatHotel] = en.hotelId;
|
||||
stat[kStatHotelLat] = @(latLon.lat);
|
||||
stat[kStatHotelLon] = @(latLon.lon);
|
||||
|
@ -229,7 +234,7 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
atLocation:[MWMLocationManager lastLocation]];
|
||||
|
||||
UIViewController * vc = static_cast<UIViewController *>([MapViewController controller]);
|
||||
NSURL * url = isDescription ? self.entity.bookingDescriptionUrl : self.entity.bookingUrl;
|
||||
NSURL * url = isDescription ? self.entity.bookingDescriptionURL : self.entity.bookingURL;
|
||||
NSAssert(url, @"Booking url can't be nil!");
|
||||
[vc openUrl:url];
|
||||
}
|
||||
|
@ -276,10 +281,10 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
withParameters:@{kStatValue : kStatAdd}];
|
||||
Framework & f = GetFramework();
|
||||
BookmarkData bmData = {self.entity.titleForNewBookmark, f.LastEditedBMType()};
|
||||
size_t const categoryIndex = f.LastEditedBMCategory();
|
||||
size_t const bookmarkIndex =
|
||||
f.GetBookmarkManager().AddBookmark(categoryIndex, self.entity.mercator, bmData);
|
||||
self.entity.bac = {categoryIndex, bookmarkIndex};
|
||||
auto const categoryIndex = static_cast<int>(f.LastEditedBMCategory());
|
||||
auto const bookmarkIndex =
|
||||
static_cast<int>(f.GetBookmarkManager().AddBookmark(categoryIndex, self.entity.mercator, bmData));
|
||||
self.entity.bac = {bookmarkIndex, categoryIndex};
|
||||
self.entity.bookmarkTitle = @(bmData.GetName().c_str());
|
||||
self.entity.bookmarkCategory = @(f.GetBmCategory(categoryIndex)->GetName().c_str());
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:kBookmarksChangedNotification
|
||||
|
@ -294,16 +299,16 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
[Statistics logEvent:kStatEventName(kStatPlacePage, kStatBookmarks)
|
||||
withParameters:@{kStatValue : kStatRemove}];
|
||||
Framework & f = GetFramework();
|
||||
BookmarkCategory * bookmarkCategory = f.GetBookmarkManager().GetBmCategory(self.entity.bac.first);
|
||||
BookmarkCategory * bookmarkCategory = f.GetBookmarkManager().GetBmCategory(self.entity.bac.m_categoryIndex);
|
||||
if (bookmarkCategory)
|
||||
{
|
||||
{
|
||||
BookmarkCategory::Guard guard(*bookmarkCategory);
|
||||
guard.m_controller.DeleteUserMark(self.entity.bac.second);
|
||||
guard.m_controller.DeleteUserMark(self.entity.bac.m_bookmarkIndex);
|
||||
}
|
||||
bookmarkCategory->SaveToKMLFile();
|
||||
}
|
||||
self.entity.bac = MakeEmptyBookmarkAndCategory();
|
||||
self.entity.bac = {};
|
||||
self.entity.bookmarkTitle = nil;
|
||||
self.entity.bookmarkCategory = nil;
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:kBookmarksChangedNotification
|
||||
|
@ -335,7 +340,7 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
return @"";
|
||||
string distance;
|
||||
CLLocationCoordinate2D const coord = lastLocation.coordinate;
|
||||
ms::LatLon const target = self.entity.latlon;
|
||||
ms::LatLon const target = self.entity.latLon;
|
||||
measurement_utils::FormatDistance(
|
||||
ms::DistanceOnEarth(coord.latitude, coord.longitude, target.lat, target.lon), distance);
|
||||
return @(distance.c_str());
|
||||
|
@ -344,26 +349,12 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
- (void)showDirectionViewWithTitle:(NSString *)title type:(NSString *)type
|
||||
{
|
||||
MWMDirectionView * directionView = self.directionView;
|
||||
UIView * ownerView = self.ownerViewController.view;
|
||||
directionView.titleLabel.text = title;
|
||||
directionView.typeLabel.text = type;
|
||||
[ownerView addSubview:directionView];
|
||||
[ownerView endEditing:YES];
|
||||
[directionView setNeedsLayout];
|
||||
MapsAppDelegate * app = [MapsAppDelegate theApp];
|
||||
[app.mapViewController updateStatusBarStyle];
|
||||
[app disableStandby];
|
||||
[directionView show];
|
||||
[self updateDistance];
|
||||
}
|
||||
|
||||
- (void)hideDirectionView
|
||||
{
|
||||
[self.directionView removeFromSuperview];
|
||||
MapsAppDelegate * app = [MapsAppDelegate theApp];
|
||||
[app.mapViewController updateStatusBarStyle];
|
||||
[app enableStandby];
|
||||
}
|
||||
|
||||
- (void)changeHeight:(CGFloat)height
|
||||
{
|
||||
if (!IPAD)
|
||||
|
@ -399,7 +390,7 @@ extern NSString * const kBookmarksChangedNotification;
|
|||
return _directionView;
|
||||
}
|
||||
|
||||
- (BOOL)isDirectionViewShown { return self.directionView.superview != nil; }
|
||||
- (void)setTopBound:(CGFloat)topBound { _topBound = self.placePage.topBound = topBound; }
|
||||
- (void)setLeftBound:(CGFloat)leftBound { _leftBound = self.placePage.leftBound = leftBound; }
|
||||
- (void)editBookmark {}
|
||||
@end
|
||||
|
|
|
@ -12,6 +12,7 @@ struct AddressInfo;
|
|||
|
||||
@class MWMMapViewControlsManager;
|
||||
@class MWMAPIBar;
|
||||
@class MWMPlacePageData;
|
||||
|
||||
@interface MapViewController : MWMViewController
|
||||
|
||||
|
@ -31,6 +32,7 @@ struct AddressInfo;
|
|||
- (void)openBookmarks;
|
||||
- (void)openMapsDownloader:(mwm::DownloaderMode)mode;
|
||||
- (void)openEditor;
|
||||
- (void)openBookmarkEditorWithData:(MWMPlacePageData *)data;
|
||||
|
||||
- (void)initialize;
|
||||
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
#import "MWMMapDownloaderViewController.h"
|
||||
#import "MWMMapViewControlsManager.h"
|
||||
#import "MWMPageController.h"
|
||||
#import "MWMPlacePageData.h"
|
||||
#import "MWMPlacePageEntity.h"
|
||||
#import "MWMPlacePageProtocol.h"
|
||||
#import "MWMRouter.h"
|
||||
#import "MWMRouterSavedState.h"
|
||||
#import "MWMSettings.h"
|
||||
|
@ -70,6 +72,8 @@ NSString * const kDownloaderSegue = @"Map2MapDownloaderSegue";
|
|||
NSString * const kMigrationSegue = @"Map2MigrationSegue";
|
||||
NSString * const kEditorSegue = @"Map2EditorSegue";
|
||||
NSString * const kUDViralAlertWasShown = @"ViralAlertWasShown";
|
||||
NSString * const kPP2BookmarkEditingSegue = @"PP2BookmarkEditing";
|
||||
|
||||
|
||||
// The first launch after process started. Used to skip "Not follow, no position" state and to run
|
||||
// locator.
|
||||
|
@ -416,7 +420,8 @@ BOOL gIsFirstMyPositionMode = YES;
|
|||
- (void)openEditor
|
||||
{
|
||||
using namespace osm_auth_ios;
|
||||
auto const & featureID = self.controlsManager.placePageEntity.info.GetID();
|
||||
|
||||
auto const & featureID = self.controlsManager.featureHolder.featureId;
|
||||
|
||||
[Statistics logEvent:kStatEditorEditStart
|
||||
withParameters:@{
|
||||
|
@ -425,7 +430,12 @@ BOOL gIsFirstMyPositionMode = YES;
|
|||
kStatEditorMWMName : @(featureID.GetMwmName().c_str()),
|
||||
kStatEditorMWMVersion : @(featureID.GetMwmVersion())
|
||||
}];
|
||||
[self performSegueWithIdentifier:kEditorSegue sender:self.controlsManager.placePageEntity];
|
||||
[self performSegueWithIdentifier:kEditorSegue sender:self.controlsManager.featureHolder];
|
||||
}
|
||||
|
||||
- (void)openBookmarkEditorWithData:(MWMPlacePageData *)data
|
||||
{
|
||||
[self performSegueWithIdentifier:kPP2BookmarkEditingSegue sender:data];
|
||||
}
|
||||
|
||||
- (void)processMyPositionStateModeEvent:(location::EMyPositionMode)mode
|
||||
|
@ -552,7 +562,12 @@ BOOL gIsFirstMyPositionMode = YES;
|
|||
if ([segue.identifier isEqualToString:kEditorSegue])
|
||||
{
|
||||
MWMEditorViewController * dvc = segue.destinationViewController;
|
||||
[dvc setFeatureToEdit:static_cast<MWMPlacePageEntity *>(sender).featureID];
|
||||
[dvc setFeatureToEdit:static_cast<id<MWMFeatureHolder>>(sender).featureId];
|
||||
}
|
||||
else if ([segue.identifier isEqualToString:kPP2BookmarkEditingSegue])
|
||||
{
|
||||
MWMEditBookmarkController * dvc = segue.destinationViewController;
|
||||
dvc.data = static_cast<MWMPlacePageData *>(sender);
|
||||
}
|
||||
else if ([segue.identifier isEqualToString:kDownloaderSegue])
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@class MWMPlacePageEntity;
|
||||
@protocol MWMPlacePageObject;
|
||||
|
||||
@interface MWMActivityViewController : UIActivityViewController
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
|||
|
||||
+ (instancetype)shareControllerForMyPosition:(CLLocationCoordinate2D const &)location;
|
||||
|
||||
+ (instancetype)shareControllerForPlacePageObject:(MWMPlacePageEntity *)entity;
|
||||
+ (instancetype)shareControllerForPlacePageObject:(id<MWMPlacePageObject>)object;
|
||||
|
||||
- (void)presentInParentViewController:(UIViewController *)parentVC anchorView:(UIView *)anchorView;
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@
|
|||
return [[self alloc] initWithActivityItem:item];
|
||||
}
|
||||
|
||||
+ (instancetype)shareControllerForPlacePageObject:(MWMPlacePageEntity *)entity
|
||||
+ (instancetype)shareControllerForPlacePageObject:(id<MWMPlacePageObject>)object;
|
||||
{
|
||||
MWMShareActivityItem * item =
|
||||
[[MWMShareActivityItem alloc] initForPlacePageObjectWithEntity:entity];
|
||||
[[MWMShareActivityItem alloc] initForPlacePageObject:object];
|
||||
return [[self alloc] initWithActivityItem:item];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,25 @@
|
|||
@class MWMPlacePageEntity;
|
||||
namespace ms
|
||||
{
|
||||
class LatLon;
|
||||
|
||||
} // namespace ms
|
||||
|
||||
@protocol MWMPlacePageObject <NSObject>
|
||||
|
||||
- (BOOL)isMyPosition;
|
||||
- (BOOL)isBooking;
|
||||
- (NSString *)title;
|
||||
- (NSString *)subtitle;
|
||||
- (NSString *)address;
|
||||
- (NSURL *)bookingDescriptionURL;
|
||||
- (NSString *)phoneNumber;
|
||||
- (ms::LatLon)latLon;
|
||||
|
||||
@end
|
||||
|
||||
@interface MWMShareActivityItem : NSObject<UIActivityItemSource>
|
||||
|
||||
- (instancetype)initForMyPositionAtLocation:(CLLocationCoordinate2D const &)location;
|
||||
- (instancetype)initForPlacePageObjectWithEntity:(MWMPlacePageEntity *)entity;
|
||||
- (instancetype)initForPlacePageObject:(id<MWMPlacePageObject>)object;
|
||||
|
||||
@end
|
||||
|
|
|
@ -15,7 +15,7 @@ NSString * httpGe0Url(NSString * shortUrl)
|
|||
|
||||
@interface MWMShareActivityItem ()
|
||||
|
||||
@property(nonatomic) MWMPlacePageEntity * entity;
|
||||
@property(nonatomic) id<MWMPlacePageObject> object;
|
||||
@property(nonatomic) CLLocationCoordinate2D location;
|
||||
@property(nonatomic) BOOL isMyPosition;
|
||||
|
||||
|
@ -34,16 +34,16 @@ NSString * httpGe0Url(NSString * shortUrl)
|
|||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initForPlacePageObjectWithEntity:(MWMPlacePageEntity *)entity
|
||||
- (instancetype)initForPlacePageObject:(id<MWMPlacePageObject>)object
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
NSAssert(entity, @"Entity can't be nil!");
|
||||
BOOL const isMyPosition = entity.isMyPosition;
|
||||
NSAssert(object, @"Entity can't be nil!");
|
||||
BOOL const isMyPosition = object.isMyPosition;
|
||||
_isMyPosition = isMyPosition;
|
||||
if (!isMyPosition)
|
||||
_entity = entity;
|
||||
_object = object;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -52,22 +52,22 @@ NSString * httpGe0Url(NSString * shortUrl)
|
|||
{
|
||||
auto & f = GetFramework();
|
||||
|
||||
auto const title = ^NSString *(MWMPlacePageEntity * entity)
|
||||
auto const title = ^NSString *(id<MWMPlacePageObject> obj)
|
||||
{
|
||||
if (!entity || entity.isMyPosition)
|
||||
if (!obj || obj.isMyPosition)
|
||||
return L(@"my_position");
|
||||
else if (entity.title.length)
|
||||
return entity.title;
|
||||
else if (entity.subtitle.length)
|
||||
return entity.subtitle;
|
||||
else if (entity.address.length)
|
||||
return entity.address;
|
||||
else if (obj.title.length)
|
||||
return obj.title;
|
||||
else if (obj.subtitle.length)
|
||||
return obj.subtitle;
|
||||
else if (obj.address.length)
|
||||
return obj.address;
|
||||
else
|
||||
return @"";
|
||||
};
|
||||
|
||||
ms::LatLon const ll = self.entity ? self.entity.latlon : ms::LatLon(self.location.latitude, self.location.longitude);
|
||||
string const s = f.CodeGe0url(ll.lat, ll.lon, f.GetDrawScale(), title(self.entity).UTF8String);
|
||||
ms::LatLon const ll = self.object ? self.object.latLon : ms::LatLon(self.location.latitude, self.location.longitude);
|
||||
string const s = f.CodeGe0url(ll.lat, ll.lon, f.GetDrawScale(), title(self.object).UTF8String);
|
||||
|
||||
NSString * url = @(s.c_str());
|
||||
if (!isShort)
|
||||
|
@ -108,7 +108,7 @@ NSString * httpGe0Url(NSString * shortUrl)
|
|||
NSString * shortUrl = [self url:YES];
|
||||
return [NSString stringWithFormat:@"%@\n%@", httpGe0Url(shortUrl),
|
||||
self.isMyPosition ? L(@"my_position_share_email_subject")
|
||||
: self.entity.title];
|
||||
: self.object.title];
|
||||
}
|
||||
|
||||
- (NSString *)itemDefaultWithActivityType:(NSString *)activityType
|
||||
|
@ -123,13 +123,13 @@ NSString * httpGe0Url(NSString * shortUrl)
|
|||
}
|
||||
|
||||
NSMutableString * result = [L(@"sharing_call_action_look") mutableCopy];
|
||||
vector<NSString *> strings{self.entity.title, self.entity.subtitle, self.entity.address,
|
||||
[self.entity getCellValue:MWMPlacePageCellTypePhoneNumber], url};
|
||||
vector<NSString *> strings{self.object.title, self.object.subtitle, self.object.address,
|
||||
self.object.phoneNumber, url};
|
||||
|
||||
if (self.entity.isBooking)
|
||||
if (self.object.isBooking)
|
||||
{
|
||||
strings.push_back(L(@"sharing_booking"));
|
||||
strings.push_back(self.entity.bookingDescriptionUrl.absoluteString);
|
||||
strings.push_back(self.object.bookingDescriptionURL.absoluteString);
|
||||
}
|
||||
|
||||
for (auto const str : strings)
|
||||
|
|
Loading…
Add table
Reference in a new issue