Merge pull request #2911 from igrechuhin/MAPSME-756

Updated downloader.
This commit is contained in:
Sergey Yershov 2016-04-20 18:47:04 +04:00
commit 1a8e28a2b5
47 changed files with 841 additions and 467 deletions

View file

@ -1,4 +1,5 @@
#import "MWMBottomMenuView.h"
#import "MWMMapDownloaderTypes.h"
#include "platform/location.hpp"
@ -6,7 +7,7 @@
@protocol MWMBottomMenuControllerProtocol<NSObject>
- (void)actionDownloadMaps;
- (void)actionDownloadMaps:(mwm::DownloaderMode)mode;
- (void)closeInfoScreens;
- (void)addPlace;
- (void)didFinishAddingPlace;

View file

@ -358,7 +358,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell)
{
[Statistics logEvent:kStatMenu withParameters:@{kStatButton : kStatDownloadMaps}];
self.state = self.restoreState;
[self.delegate actionDownloadMaps];
[self.delegate actionDownloadMaps:mwm::DownloaderMode::Downloaded];
}
- (void)menuActionOpenSettings

View file

@ -255,7 +255,7 @@ extern NSString * const kAlohalyticsTapEventKey;
#pragma mark - MWMSearchManagerProtocol & MWMBottomMenuControllerProtocol
- (void)actionDownloadMaps
- (void)actionDownloadMaps:(mwm::DownloaderMode)mode
{
if (platform::migrate::NeedMigrate())
{
@ -272,7 +272,7 @@ extern NSString * const kAlohalyticsTapEventKey;
}
else
{
[self.ownerController openMapsDownloader];
[self.ownerController openMapsDownloader:mode];
}
}

View file

@ -1,4 +1,5 @@
#import "MWMAlertViewController.h"
#import "MWMMapDownloaderTypes.h"
#import "MWMSearchTextField.h"
#import "MWMSearchView.h"
@ -15,7 +16,7 @@ typedef NS_ENUM(NSUInteger, MWMSearchManagerState)
@property (nonnull, nonatomic, readonly) MWMAlertViewController * alertController;
- (void)searchViewDidEnterState:(MWMSearchManagerState)state;
- (void)actionDownloadMaps;
- (void)actionDownloadMaps:(mwm::DownloaderMode)mode;
@end

View file

@ -220,7 +220,7 @@ extern NSString * const kSearchStateKey = @"SearchStateKey";
- (void)handleDownloadMapsAction
{
[self.delegate actionDownloadMaps];
[self.delegate actionDownloadMaps:mwm::DownloaderMode::Available];
}
#pragma mark - State changes

View file

@ -0,0 +1,14 @@
#import "MWMMapDownloaderTableViewCellProtocol.h"
#import "MWMTableViewCell.h"
@protocol MWMMapDownloaderButtonTableViewCellProtocol <NSObject>
- (void)openAvailableMaps;
@end
@interface MWMMapDownloaderButtonTableViewCell : MWMTableViewCell <MWMMapDownloaderTableViewCellProtocol>
@property (weak, nonatomic) id<MWMMapDownloaderButtonTableViewCellProtocol> delegate;
@end

View file

@ -0,0 +1,39 @@
#import "MWMMapDownloaderButtonTableViewCell.h"
#include "storage/storage.hpp"
using namespace storage;
@implementation MWMMapDownloaderButtonTableViewCell
+ (CGFloat)estimatedHeight
{
return 44.0;
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self config];
}
- (void)prepareForReuse
{
[super prepareForReuse];
[self config];
}
- (void)config
{
if ([self respondsToSelector:@selector(setSeparatorInset:)])
[self setSeparatorInset:UIEdgeInsetsZero];
if ([self respondsToSelector:@selector(setLayoutMargins:)])
[self setLayoutMargins:UIEdgeInsetsZero];
}
- (IBAction)buttonPressed
{
[self.delegate openAvailableMaps];
}
@end

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="0.0" shouldIndentWhileEditing="NO" reuseIdentifier="MWMMapDownloaderButtonTableViewCell" id="KGk-i7-Jjw" customClass="MWMMapDownloaderButtonTableViewCell">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="22f-XO-fEh">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="ppe-HK-X6q"/>
</constraints>
<state key="normal" title="Button"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="download_maps"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="buttonPressed" destination="KGk-i7-Jjw" eventType="touchUpInside" id="wi2-kT-ib1"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="22f-XO-fEh" secondAttribute="bottom" id="Dmd-Qj-hkL"/>
<constraint firstItem="22f-XO-fEh" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="VTQ-nl-h3g"/>
<constraint firstAttribute="trailing" secondItem="22f-XO-fEh" secondAttribute="trailing" id="j9Y-lb-BeQ"/>
<constraint firstItem="22f-XO-fEh" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="rRj-TU-xPW"/>
</constraints>
</tableViewCellContentView>
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</tableViewCell>
</objects>
</document>

View file

@ -18,7 +18,7 @@ namespace
@interface MWMMapDownloaderPlaceTableViewCell ()
@property (weak, nonatomic) IBOutlet UILabel * area;
@property (weak, nonatomic) IBOutlet UILabel * descriptionLabel;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * titleBottomOffset;
@end
@ -35,7 +35,7 @@ namespace
[super layoutSubviews];
if (isIOS7)
{
self.area.preferredMaxLayoutWidth = self.area.width;
self.descriptionLabel.preferredMaxLayoutWidth = self.descriptionLabel.width;
[super layoutSubviews];
}
}
@ -45,18 +45,25 @@ namespace
- (void)config:(storage::NodeAttrs const &)nodeAttrs
{
[super config:nodeAttrs];
BOOL isAreaVisible = NO;
BOOL isDescriptionVisible = NO;
if (self.needDisplayArea && nodeAttrs.m_topmostParentInfo.size() == 1)
{
string const & areaName = nodeAttrs.m_topmostParentInfo[0].m_localName;
isAreaVisible = (areaName != GetFramework().Storage().GetRootId());
if (isAreaVisible)
self.area.attributedText = [self matchedString:@(areaName.c_str())
selectedAttrs:kSelectedAreaAttrs
unselectedAttrs:kUnselectedAreaAttrs];
isDescriptionVisible = (areaName != GetFramework().Storage().GetRootId());
if (isDescriptionVisible)
self.descriptionLabel.attributedText = [self matchedString:@(areaName.c_str())
selectedAttrs:kSelectedAreaAttrs
unselectedAttrs:kUnselectedAreaAttrs];
}
self.area.hidden = !isAreaVisible;
self.titleBottomOffset.priority = isAreaVisible ? UILayoutPriorityDefaultLow : UILayoutPriorityDefaultHigh;
else if (!nodeAttrs.m_nodeLocalDescription.empty())
{
isDescriptionVisible = YES;
self.descriptionLabel.attributedText = [self matchedString:@(nodeAttrs.m_nodeLocalDescription.c_str())
selectedAttrs:kSelectedAreaAttrs
unselectedAttrs:kUnselectedAreaAttrs];
}
self.descriptionLabel.hidden = !isDescriptionVisible;
self.titleBottomOffset.priority = isDescriptionVisible ? UILayoutPriorityDefaultLow : UILayoutPriorityDefaultHigh;
}
@end

View file

@ -11,7 +11,7 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="62"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="1KI-85-wsU" id="mRF-11-OKU">
<rect key="frame" x="0.0" y="0.0" width="320" height="61.5"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="61"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Yb5-r1-Z2X">
@ -76,7 +76,7 @@
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="area" destination="fev-4l-MY3" id="6xU-Oo-rem"/>
<outlet property="descriptionLabel" destination="fev-4l-MY3" id="lyN-5S-iWE"/>
<outlet property="downloadSize" destination="rqh-iy-Sx9" id="g9R-G7-dxQ"/>
<outlet property="stateWrapper" destination="Yb5-r1-Z2X" id="iPW-N5-qJi"/>
<outlet property="title" destination="3Db-Yq-FlD" id="qtt-YF-a0V"/>

View file

@ -11,7 +11,7 @@
<rect key="frame" x="0.0" y="0.0" width="320" height="82"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="1KI-85-wsU" id="mRF-11-OKU">
<rect key="frame" x="0.0" y="0.0" width="320" height="81.5"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="81"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Yb5-r1-Z2X">
@ -89,7 +89,7 @@
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="area" destination="fev-4l-MY3" id="3BY-9T-0E9"/>
<outlet property="descriptionLabel" destination="fev-4l-MY3" id="1C2-OF-Vhu"/>
<outlet property="downloadSize" destination="rqh-iy-Sx9" id="q4T-Pv-DrI"/>
<outlet property="stateWrapper" destination="Yb5-r1-Z2X" id="eb8-Ut-gh5"/>
<outlet property="subPlace" destination="x7m-Zm-8y6" id="63W-Bc-FdX"/>

View file

@ -1,19 +1,16 @@
#import "MWMFrameworkObservers.h"
#import "MWMMapDownloaderProtocol.h"
#import "MWMMapDownloaderTableViewCellProtocol.h"
#import "MWMMapDownloaderTypes.h"
#import "MWMTableViewCell.h"
#include "storage/storage.hpp"
@protocol MWMMapDownloaderTableViewCellProtocol <NSObject>
+ (CGFloat)estimatedHeight;
@end
@interface MWMMapDownloaderTableViewCell : MWMTableViewCell <MWMMapDownloaderTableViewCellProtocol, MWMFrameworkStorageObserver>
@property (nonatomic) BOOL isHeightCell;
@property (weak, nonatomic) id<MWMMapDownloaderProtocol> delegate;
@property (nonatomic) mwm::DownloaderMode mode;
- (void)config:(storage::NodeAttrs const &)nodeAttrs;
- (void)setCountryId:(NSString *)countryId searchQuery:(NSString *)query;

View file

@ -1,5 +1,6 @@
#import "Common.h"
#import "MWMCircularProgress.h"
#import "MWMMapDownloaderLargeCountryTableViewCell.h"
#import "MWMMapDownloaderTableViewCell.h"
#import "NSString+Categories.h"
#import "UIFont+MapsMeFonts.h"
@ -84,14 +85,21 @@ namespace
- (void)configProgress:(storage::NodeAttrs const &)nodeAttrs
{
MWMCircularProgress * progress = self.progress;
MWMButtonColoring const coloring = self.mode == mwm::DownloaderMode::Downloaded
? MWMButtonColoringBlack
: MWMButtonColoringBlue;
switch (nodeAttrs.m_status)
{
case NodeStatus::NotDownloaded:
case NodeStatus::Partly:
{
auto const affectedStates = {MWMCircularProgressStateNormal, MWMCircularProgressStateSelected};
[progress setImage:[UIImage imageNamed:@"ic_download"] forStates:affectedStates];
[progress setColoring:MWMButtonColoringBlack forStates:affectedStates];
MWMCircularProgressStateVec const affectedStates = {MWMCircularProgressStateNormal,
MWMCircularProgressStateSelected};
UIImage * image = [self isKindOfClass:[MWMMapDownloaderLargeCountryTableViewCell class]]
? [UIImage imageNamed:@"ic_folder"]
: [UIImage imageNamed:@"ic_download"];
[progress setImage:image forStates:affectedStates];
[progress setColoring:coloring forStates:affectedStates];
progress.state = MWMCircularProgressStateNormal;
break;
}
@ -113,7 +121,8 @@ namespace
break;
case NodeStatus::OnDiskOutOfDate:
{
auto const affectedStates = {MWMCircularProgressStateNormal, MWMCircularProgressStateSelected};
MWMCircularProgressStateVec const affectedStates = {MWMCircularProgressStateNormal,
MWMCircularProgressStateSelected};
[progress setImage:[UIImage imageNamed:@"ic_update"] forStates:affectedStates];
[progress setColoring:MWMButtonColoringOther forStates:affectedStates];
progress.state = MWMCircularProgressStateNormal;
@ -150,7 +159,10 @@ namespace
{
case NodeStatus::NotDownloaded:
case NodeStatus::Partly:
[self.delegate downloadNode:m_countryId];
if ([self isKindOfClass:[MWMMapDownloaderLargeCountryTableViewCell class]])
[self.delegate openNodeSubtree:m_countryId];
else
[self.delegate downloadNode:m_countryId];
break;
case NodeStatus::Undefined:
case NodeStatus::Error:

View file

@ -0,0 +1,5 @@
@protocol MWMMapDownloaderTableViewCellProtocol <NSObject>
+ (CGFloat)estimatedHeight;
@end

View file

@ -1,19 +1,22 @@
#import "MWMMapDownloaderButtonTableViewCell.h"
#import "MWMMapDownloaderProtocol.h"
#import "MWMMapDownloaderTableViewCell.h"
#import "MWMMapDownloaderTypes.h"
#include "storage/index.hpp"
@interface MWMMapDownloaderDataSource : NSObject <UITableViewDataSource>
@property (nonatomic, readonly) BOOL isParentRoot;
@property (nonatomic, readonly) BOOL needFullReload;
@property (nonatomic, readonly) NSMutableIndexSet * reloadSections;
@property (nonatomic, readonly) mwm::DownloaderMode mode;
@property (weak, nonatomic, readonly) id<MWMMapDownloaderProtocol, MWMMapDownloaderButtonTableViewCellProtocol> delegate;
- (instancetype)initWithDelegate:(id<MWMMapDownloaderProtocol>)delegate;
- (instancetype)initWithDelegate:(id<MWMMapDownloaderProtocol, MWMMapDownloaderButtonTableViewCellProtocol>)delegate mode:(mwm::DownloaderMode)mode;
- (NSString *)parentCountryId;
- (NSString *)countryIdForIndexPath:(NSIndexPath *)indexPath;
- (NSString *)cellIdentifierForIndexPath:(NSIndexPath *)indexPath;
- (void)fillCell:(MWMMapDownloaderTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
- (void)fillCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
- (BOOL)isButtonCell:(NSInteger)section;
- (NSString *)searchMatchedResultForCountryId:(NSString *)countryId;

View file

@ -3,39 +3,33 @@
#import "MWMMapDownloaderLargeCountryTableViewCell.h"
#import "MWMMapDownloaderPlaceTableViewCell.h"
#import "MWMMapDownloaderSubplaceTableViewCell.h"
#import "MWMMapDownloaderTypes.h"
#include "Framework.h"
using namespace storage;
@interface MWMMapDownloaderDataSource ()
@property (weak, nonatomic) id<MWMMapDownloaderProtocol> delegate;
@property (nonatomic, readwrite) BOOL needFullReload;
@end
@implementation MWMMapDownloaderDataSource
- (instancetype)initWithDelegate:(id<MWMMapDownloaderProtocol>)delegate
- (instancetype)initWithDelegate:(id<MWMMapDownloaderProtocol, MWMMapDownloaderButtonTableViewCellProtocol>)delegate mode:(mwm::DownloaderMode)mode
{
self = [super init];
if (self)
{
_delegate = delegate;
_reloadSections = [NSMutableIndexSet indexSet];
_mode = mode;
}
return self;
}
#pragma mark - Fill cells with data
- (void)fillCell:(MWMMapDownloaderTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
- (void)fillCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSString * countryId = [self countryIdForIndexPath:indexPath];
[cell setCountryId:countryId searchQuery:[self searchQuery]];
if (![cell isKindOfClass:[MWMMapDownloaderTableViewCell class]])
return;
NSString * countryId = [self countryIdForIndexPath:indexPath];
if ([cell isKindOfClass:[MWMMapDownloaderPlaceTableViewCell class]])
{
MWMMapDownloaderPlaceTableViewCell * placeCell = static_cast<MWMMapDownloaderPlaceTableViewCell *>(cell);
@ -47,6 +41,9 @@ using namespace storage;
MWMMapDownloaderSubplaceTableViewCell * subplaceCell = static_cast<MWMMapDownloaderSubplaceTableViewCell *>(cell);
[subplaceCell setSubplaceText:[self searchMatchedResultForCountryId:countryId]];
}
MWMMapDownloaderTableViewCell * tCell = static_cast<MWMMapDownloaderTableViewCell *>(cell);
[tCell setCountryId:countryId searchQuery:[self searchQuery]];
}
#pragma mark - UITableViewDataSource
@ -61,6 +58,7 @@ using namespace storage;
NSString * reuseIdentifier = [self cellIdentifierForIndexPath:indexPath];
MWMMapDownloaderTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
cell.delegate = self.delegate;
cell.mode = self.mode;
[self fillCell:cell atIndexPath:indexPath];
return cell;
}
@ -108,11 +106,11 @@ using namespace storage;
return nil;
}
- (void)setNeedFullReload:(BOOL)needFullReload
#pragma mark - Helpers
- (BOOL)isButtonCell:(NSInteger)section
{
_needFullReload = needFullReload;
if (needFullReload)
[self.reloadSections removeAllIndexes];
return NO;
}
@end

View file

@ -2,7 +2,7 @@
@interface MWMMapDownloaderDefaultDataSource : MWMMapDownloaderDataSource
- (instancetype)initForRootCountryId:(NSString *)countryId delegate:(id<MWMMapDownloaderProtocol>)delegate;
- (void)reload;
- (instancetype)initForRootCountryId:(NSString *)countryId delegate:(id<MWMMapDownloaderProtocol, MWMMapDownloaderButtonTableViewCellProtocol>)delegate mode:(mwm::DownloaderMode)mode;
- (void)load;
@end

View file

@ -1,4 +1,5 @@
#import "Common.h"
#import "MWMMapDownloaderButtonTableViewCell.h"
#import "MWMMapDownloaderDefaultDataSource.h"
#import "MWMStorage.h"
#import "Statistics.h"
@ -9,6 +10,7 @@ extern NSString * const kCountryCellIdentifier;
extern NSString * const kSubplaceCellIdentifier;
extern NSString * const kPlaceCellIdentifier;
extern NSString * const kLargeCountryCellIdentifier;
extern NSString * const kButtonCellIdentifier;
namespace
{
@ -27,12 +29,7 @@ auto compareLocalNames = ^NSComparisonResult(NSString * s1, NSString * s2)
} // namespace
using namespace storage;
@interface MWMMapDownloaderDataSource ()
@property (nonatomic, readwrite) BOOL needFullReload;
@end
using namespace mwm;
@interface MWMMapDownloaderDefaultDataSource ()
@ -49,9 +46,9 @@ using namespace storage;
@synthesize isParentRoot = _isParentRoot;
- (instancetype)initForRootCountryId:(NSString *)countryId delegate:(id<MWMMapDownloaderProtocol>)delegate
- (instancetype)initForRootCountryId:(NSString *)countryId delegate:(id<MWMMapDownloaderProtocol, MWMMapDownloaderButtonTableViewCellProtocol>)delegate mode:(DownloaderMode)mode
{
self = [super initWithDelegate:delegate];
self = [super initWithDelegate:delegate mode:mode];
if (self)
{
m_parentId = countryId.UTF8String;
@ -66,45 +63,18 @@ using namespace storage;
auto const & s = GetFramework().Storage();
TCountriesVec downloadedChildren;
TCountriesVec availableChildren;
s.GetChildrenInGroups(m_parentId, downloadedChildren, availableChildren);
[self configAvailableSections:availableChildren];
[self configDownloadedSection:downloadedChildren];
}
- (void)reload
{
[self.reloadSections removeAllIndexes];
// Get old data for comparison.
NSDictionary<NSString *, NSArray<NSString *> *> * availableCountriesBeforeUpdate = self.availableCountries;
NSInteger const downloadedCountriesCountBeforeUpdate = self.downloadedCountries.count;
// Load updated data.
[self load];
// Compare new data vs old data to understand what kind of reload is required and what sections need reload.
NSInteger const downloadedCountriesCountAfterUpdate = self.downloadedCountries.count;
self.needFullReload =
(downloadedCountriesCountBeforeUpdate == 0 || downloadedCountriesCountAfterUpdate == 0 ||
availableCountriesBeforeUpdate.count != self.availableCountries.count ||
availableCountriesBeforeUpdate.count == 0);
if (self.needFullReload)
return;
[availableCountriesBeforeUpdate enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSArray<NSString *> * obj, BOOL * stop)
s.GetChildrenInGroups(m_parentId, downloadedChildren, availableChildren, true /* keepAvailableChildren */);
if (self.mode == DownloaderMode::Available)
{
NSUInteger const sectionIndex = [self.indexes indexOfObject:key];
if (sectionIndex == NSNotFound)
{
self.needFullReload = YES;
*stop = YES;
}
else if (obj.count != self.availableCountries[key].count)
{
[self.reloadSections addIndex:sectionIndex];
}
}];
[self.reloadSections shiftIndexesStartingAtIndex:0 by:self.downloadedSectionShift];
if (downloadedCountriesCountBeforeUpdate != downloadedCountriesCountAfterUpdate)
[self.reloadSections addIndex:self.downloadedSection];
self.downloadedCountries = nil;
[self configAvailableSections:availableChildren];
}
else
{
self.indexes = nil;
self.availableCountries = nil;
[self configDownloadedSection:downloadedChildren];
}
}
- (void)configAvailableSections:(TCountriesVec const &)availableChildren
@ -145,17 +115,35 @@ using namespace storage;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.indexes.count + self.downloadedSectionShift;
if (self.downloadedCountries)
return self.isParentRoot ? 2 : 1;
return self.indexes.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == self.downloadedSection)
if ([self isButtonCell:section])
return 1;
if (self.downloadedCountries)
return self.downloadedCountries.count;
NSString * index = self.indexes[section - self.downloadedSectionShift];
NSString * index = self.indexes[section];
return self.availableCountries[index].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self isButtonCell:indexPath.section])
{
MWMMapDownloaderButtonTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:kButtonCellIdentifier];
cell.delegate = self.delegate;
return cell;
}
else
{
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
}
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return self.isParentRoot ? self.indexes : nil;
@ -163,13 +151,15 @@ using namespace storage;
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return index + self.downloadedSectionShift;
return index;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if (section == self.downloadedSection)
if (self.downloadedCountries)
{
if ([self isButtonCell:section])
return @"";
NodeAttrs nodeAttrs;
GetFramework().Storage().GetNodeAttrs(m_parentId, nodeAttrs);
if (nodeAttrs.m_localMwmSize == 0)
@ -177,7 +167,7 @@ using namespace storage;
else
return [NSString stringWithFormat:@"%@ (%@)", L(@"downloader_downloaded_subtitle"), formattedSize(nodeAttrs.m_localMwmSize)];
}
return self.indexes[section - self.downloadedSectionShift];
return self.indexes[section];
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
@ -187,6 +177,8 @@ using namespace storage;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self isButtonCell:indexPath.section])
return NO;
NodeAttrs nodeAttrs;
GetFramework().Storage().GetNodeAttrs([self countryIdForIndexPath:indexPath].UTF8String, nodeAttrs);
NodeStatus const status = nodeAttrs.m_status;
@ -204,9 +196,9 @@ using namespace storage;
{
NSInteger const section = indexPath.section;
NSInteger const row = indexPath.row;
if (section == self.downloadedSection)
if (self.downloadedCountries)
return self.downloadedCountries[row];
NSString * index = self.indexes[section - self.downloadedSectionShift];
NSString * index = self.indexes[section];
NSArray<NSString *> * availableCountries = self.availableCountries[index];
NSString * nsCountryId = availableCountries[indexPath.row];
return nsCountryId;
@ -223,16 +215,11 @@ using namespace storage;
return self.isParentRoot ? kCountryCellIdentifier : kPlaceCellIdentifier;
}
#pragma mark - Properties
#pragma mark - Helpers
- (NSInteger)downloadedSectionShift
- (BOOL)isButtonCell:(NSInteger)section
{
return (self.downloadedCountries.count != 0 ? self.downloadedSection + 1 : 0);
}
- (NSInteger)downloadedSection
{
return self.downloadedCountries.count != 0 ? 0 : NSNotFound;
return self.downloadedCountries && self.isParentRoot && section != 0;
}
@end

View file

@ -6,12 +6,6 @@
using namespace storage;
@interface MWMMapDownloaderDataSource ()
@property (nonatomic, readwrite) BOOL needFullReload;
@end
@interface MWMMapDownloaderDefaultDataSource ()
@property (nonatomic, readonly) NSInteger downloadedCountrySection;
@ -31,24 +25,8 @@ using namespace storage;
- (void)load
{
[super load];
[self configNearMeSection];
}
- (void)reload
{
NSInteger const closestCoutriesCountBeforeUpdate = self.nearmeCountries.count;
[super reload];
NSInteger const closestCoutriesCountAfterUpdate = self.nearmeCountries.count;
if (closestCoutriesCountBeforeUpdate != closestCoutriesCountAfterUpdate &&
(closestCoutriesCountBeforeUpdate == 0 || closestCoutriesCountAfterUpdate == 0))
self.needFullReload = YES;
if (self.needFullReload)
return;
[self.reloadSections shiftIndexesStartingAtIndex:0 by:self.nearmeSectionShift];
if (closestCoutriesCountBeforeUpdate != closestCoutriesCountAfterUpdate)
[self.reloadSections addIndex:self.nearmeSection];
if (self.mode == mwm::DownloaderMode::Available)
[self configNearMeSection];
}
- (void)configNearMeSection
@ -60,14 +38,8 @@ using namespace storage;
TCountriesVec closestCoutryIds;
countryInfoGetter.GetRegionsCountryId(lm.lastLocation.mercator, closestCoutryIds);
NSMutableArray<NSString *> * nearmeCountries = [@[] mutableCopy];
auto const & s = GetFramework().Storage();
for (auto const & countryId : closestCoutryIds)
{
NodeStatuses nodeStatuses{};
s.GetNodeStatuses(countryId, nodeStatuses);
if (nodeStatuses.m_status == NodeStatus::NotDownloaded)
[nearmeCountries addObject:@(countryId.c_str())];
}
[nearmeCountries addObject:@(countryId.c_str())];
self.nearmeCountries = nearmeCountries;
}

View file

@ -4,6 +4,6 @@
@interface MWMMapDownloaderSearchDataSource : MWMMapDownloaderDataSource
- (instancetype)initWithSearchResults:(DownloaderSearchResults const &)results delegate:(id<MWMMapDownloaderProtocol>)delegate;
- (instancetype)initWithSearchResults:(DownloaderSearchResults const &)results delegate:(id<MWMMapDownloaderProtocol, MWMMapDownloaderButtonTableViewCellProtocol>)delegate;
@end

View file

@ -19,9 +19,9 @@ extern NSString * const kLargeCountryCellIdentifier;
@implementation MWMMapDownloaderSearchDataSource
- (instancetype)initWithSearchResults:(DownloaderSearchResults const &)results delegate:(id<MWMMapDownloaderProtocol>)delegate
- (instancetype)initWithSearchResults:(DownloaderSearchResults const &)results delegate:(id<MWMMapDownloaderProtocol, MWMMapDownloaderButtonTableViewCellProtocol>)delegate
{
self = [super initWithDelegate:delegate];
self = [super initWithDelegate:delegate mode:mwm::DownloaderMode::Available];
if (self)
{
NSMutableOrderedSet<NSString *> * nsSearchCountryIds =
@ -89,9 +89,4 @@ extern NSString * const kLargeCountryCellIdentifier;
return self.searchMatchedResults[countryId];
}
- (BOOL)needFullReload
{
return YES;
}
@end

View file

@ -1,16 +1,13 @@
#import "MWMMapDownloaderButtonTableViewCell.h"
#import "MWMMapDownloaderProtocol.h"
#import "MWMMapDownloaderTableViewCell.h"
#import "MWMMapDownloaderTypes.h"
#import "MWMViewController.h"
@interface MWMBaseMapDownloaderViewController : MWMViewController <UITableViewDelegate, MWMMapDownloaderProtocol>
@property (weak, nonatomic) IBOutlet UILabel * allMapsLabel;
@property (nonatomic) BOOL showAllMapsView;
@property (nonatomic) NSString * parentCountryId;
@interface MWMBaseMapDownloaderViewController : MWMViewController <UITableViewDelegate, MWMMapDownloaderProtocol, MWMMapDownloaderButtonTableViewCellProtocol>
- (void)configTable;
- (void)configAllMapsView;
- (void)setParentCountryId:(NSString *)parentId mode:(mwm::DownloaderMode)mode;
@end

View file

@ -1,6 +1,7 @@
#import "Common.h"
#import "MapsAppDelegate.h"
#import "MWMAlertViewController.h"
#import "MWMButton.h"
#import "MWMFrameworkListener.h"
#import "MWMMapDownloaderDefaultDataSource.h"
#import "MWMMapDownloaderLargeCountryTableViewCell.h"
@ -12,37 +13,61 @@
#import "MWMStorage.h"
#import "Statistics.h"
#import "UIColor+MapsMeColor.h"
#import "UIViewController+Navigation.h"
#include "Framework.h"
#include "storage/index.hpp"
extern NSString * const kButtonCellIdentifier = @"MWMMapDownloaderButtonTableViewCell";
extern NSString * const kCountryCellIdentifier = @"MWMMapDownloaderTableViewCell";
extern NSString * const kSubplaceCellIdentifier = @"MWMMapDownloaderSubplaceTableViewCell";
extern NSString * const kPlaceCellIdentifier = @"MWMMapDownloaderPlaceTableViewCell";
extern NSString * const kLargeCountryCellIdentifier = @"MWMMapDownloaderLargeCountryTableViewCell";
extern NSString * const kPlaceCellIdentifier = @"MWMMapDownloaderPlaceTableViewCell";
extern NSString * const kSubplaceCellIdentifier = @"MWMMapDownloaderSubplaceTableViewCell";
namespace
{
NSString * const kAllMapsLabelFormat = @"%@ %@ (%@)";
typedef NS_OPTIONS(NSUInteger, ActionButtons)
{
NoAction = 0,
ShowOnMapAction = 1 << 1,
DownloadAction = 1 << 2,
UpdateAction = 1 << 3,
CancelDownloadAction = 1 << 4,
RetryDownloadAction = 1 << 5,
DeleteAction = 1 << 6
};
NSString * const kAllMapsLabelFormat = @"%@ (%@)";
NSString * const kCancelActionTitle = L(@"cancel");
NSString * const kCancelAllTitle = L(@"downloader_cancel_all");
NSString * const kCancelDownloadActionTitle = L(@"cancel_download");
NSString * const kDeleteActionTitle = L(@"downloader_delete_map");
NSString * const kDownloaAllTitle = L(@"downloader_download_all_button");
NSString * const kDownloadActionTitle = L(@"downloader_download_map");
NSString * const kDownloadAllActionTitle = L(@"downloader_download_all_button");
NSString * const kDownloadingTitle = L(@"downloader_downloading");
NSString * const kMapsTitle = L(@"downloader_maps");
NSString * const kShowActionTitle = L(@"zoom_to_country");
NSString * const kRetryActionTitle = L(@"downloader_retry");
NSString * const kShowOnMapActionTitle = L(@"zoom_to_country");
NSString * const kUpdateActionTitle = L(@"downloader_status_outdated");
NSString * const kUpdateAllTitle = L(@"downloader_update_all_button");
NSString * const kBaseControllerIdentifier = @"MWMBaseMapDownloaderViewController";
NSString * const kControllerIdentifier = @"MWMMapDownloaderViewController";
} // namespace
@interface MWMBaseMapDownloaderViewController () <UIActionSheetDelegate, MWMFrameworkStorageObserver>
using namespace storage;
using namespace mwm;
@interface MWMBaseMapDownloaderViewController () <UIActionSheetDelegate, UIScrollViewDelegate, MWMFrameworkStorageObserver>
@property (weak, nonatomic) IBOutlet UITableView * tableView;
@property (weak, nonatomic) IBOutlet UIView * allMapsView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint * allMapsViewBottomOffset;
@property (weak, nonatomic) IBOutlet UIButton * allMapsButton;
@property (weak, nonatomic) IBOutlet MWMButton * allMapsButton;
@property (weak, nonatomic) IBOutlet MWMButton * allMapsCancelButton;
@property (nonatomic) UIImage * navBarBackground;
@property (nonatomic) UIImage * navBarShadow;
@ -58,9 +83,12 @@ NSString * const kUpdateActionTitle = L(@"downloader_status_outdated");
@property (nonatomic) BOOL skipCountryEventProcessing;
@property (nonatomic) BOOL forceFullReload;
@end
@property (nonatomic, readonly) NSString * parentCountryId;
@property (nonatomic, readonly) DownloaderMode mode;
using namespace storage;
@property (nonatomic) BOOL showAllMapsButtons;
@end
@implementation MWMBaseMapDownloaderViewController
{
@ -72,7 +100,6 @@ using namespace storage;
[super viewDidLoad];
[self configNavBar];
[self configTable];
[self configAllMapsView];
}
- (void)viewWillAppear:(BOOL)animated
@ -86,6 +113,7 @@ using namespace storage;
forBarMetrics:UIBarMetricsDefault];
navBar.shadowImage = [[UIImage alloc] init];
[MWMFrameworkListener addObserver:self];
[self configViews];
}
- (void)viewWillDisappear:(BOOL)animated
@ -98,11 +126,17 @@ using namespace storage;
[self notifyParentController];
}
- (void)configViews
{
[self configAllMapsView];
}
- (void)configNavBar
{
BOOL const downloaded = self.mode == DownloaderMode::Downloaded;
if (self.dataSource.isParentRoot)
{
self.title = L(@"download_maps");
self.title = downloaded ? L(@"downloader_my_maps_title") : L(@"download_maps");
}
else
{
@ -110,6 +144,13 @@ using namespace storage;
GetFramework().Storage().GetNodeAttrs(self.parentCountryId.UTF8String, nodeAttrs);
self.title = @(nodeAttrs.m_nodeLocalName.c_str());
}
if (downloaded)
{
UIBarButtonItem * addButton = [self buttonWithImage:[UIImage imageNamed:@"ic_nav_bar_add"]
action:@selector(openAvailableMaps)];
self.navigationItem.rightBarButtonItems = [self alignedNavBarButtonItems:@[ addButton ]];
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
@ -138,8 +179,11 @@ using namespace storage;
if (self.skipCountryEventProcessing)
return;
for (MWMMapDownloaderTableViewCell * cell in self.tableView.visibleCells)
[cell processCountryEvent:countryId];
for (UITableViewCell * cell in self.tableView.visibleCells)
{
if ([cell conformsToProtocol:@protocol(MWMFrameworkStorageObserver)])
[static_cast<id<MWMFrameworkStorageObserver>>(cell) processCountryEvent:countryId];
}
BOOL needReload = NO;
auto const & s = GetFramework().Storage();
@ -150,15 +194,18 @@ using namespace storage;
});
if (needReload)
{
[self configAllMapsView];
[self configViews];
[self reloadData];
}
}
- (void)processCountry:(TCountryId const &)countryId progress:(MapFilesDownloader::TProgress const &)progress
{
for (MWMMapDownloaderTableViewCell * cell in self.tableView.visibleCells)
[cell processCountry:countryId progress:progress];
for (UITableViewCell * cell in self.tableView.visibleCells)
{
if ([cell conformsToProtocol:@protocol(MWMFrameworkStorageObserver)])
[static_cast<id<MWMFrameworkStorageObserver>>(cell) processCountry:countryId progress:progress];
}
}
#pragma mark - Table
@ -180,106 +227,7 @@ using namespace storage;
[self registerCellWithIdentifier:kCountryCellIdentifier];
[self registerCellWithIdentifier:kLargeCountryCellIdentifier];
[self registerCellWithIdentifier:kSubplaceCellIdentifier];
}
- (void)showActionSheetForRowAtIndexPath:(NSIndexPath *)indexPath
{
auto const & s = GetFramework().Storage();
NodeAttrs nodeAttrs;
m_actionSheetId = [self.dataSource countryIdForIndexPath:indexPath].UTF8String;
s.GetNodeAttrs(m_actionSheetId, nodeAttrs);
BOOL const needsUpdate = (nodeAttrs.m_status == NodeStatus::OnDiskOutOfDate);
BOOL const isDownloaded = (needsUpdate || nodeAttrs.m_status == NodeStatus::OnDisk);
NSString * title = @(nodeAttrs.m_nodeLocalName.c_str());
BOOL const isMultiParent = (nodeAttrs.m_parentInfo.size() > 1);
NSString * message = (self.dataSource.isParentRoot || isMultiParent)
? nil
: @(nodeAttrs.m_parentInfo[0].m_localName.c_str());
NSString * downloadActionTitle = [NSString
stringWithFormat:@"%@, %@", kDownloadActionTitle, formattedSize(nodeAttrs.m_mwmSize)];
if (isIOS7)
{
UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIView * cellSuperView = cell.superview;
if (!cellSuperView)
return;
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:title
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
if (isDownloaded)
{
[actionSheet addButtonWithTitle:kShowActionTitle];
if (needsUpdate)
[actionSheet addButtonWithTitle:kUpdateActionTitle];
[actionSheet addButtonWithTitle:kDeleteActionTitle];
actionSheet.destructiveButtonIndex = actionSheet.numberOfButtons - 1;
}
else
{
[actionSheet addButtonWithTitle:downloadActionTitle];
}
if (!IPAD)
{
[actionSheet addButtonWithTitle:kCancelActionTitle];
actionSheet.cancelButtonIndex = actionSheet.numberOfButtons - 1;
}
[actionSheet showFromRect:cell.frame inView:cellSuperView animated:YES];
}
else
{
UIAlertController * alertController =
[UIAlertController alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleActionSheet];
UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:indexPath];
alertController.popoverPresentationController.sourceView = cell;
alertController.popoverPresentationController.sourceRect = cell.bounds;
if (isDownloaded)
{
UIAlertAction * showAction = [UIAlertAction actionWithTitle:kShowActionTitle
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[self showNode:self->m_actionSheetId];
}];
[alertController addAction:showAction];
if (needsUpdate)
{
UIAlertAction * updateAction = [UIAlertAction actionWithTitle:kUpdateActionTitle
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[self updateNode:self->m_actionSheetId];
}];
[alertController addAction:updateAction];
}
UIAlertAction * deleteAction = [UIAlertAction actionWithTitle:kDeleteActionTitle
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action)
{
[self deleteNode:self->m_actionSheetId];
}];
[alertController addAction:deleteAction];
}
else
{
UIAlertAction * downloadAction = [UIAlertAction actionWithTitle:downloadActionTitle
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[self downloadNode:self->m_actionSheetId];
}];
[alertController addAction:downloadAction];
}
UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:kCancelActionTitle
style:UIAlertActionStyleCancel
handler:nil];
[alertController addAction:cancelAction];
[self presentViewController:alertController animated:YES completion:nil];
}
[self registerCellWithIdentifier:kButtonCellIdentifier];
}
#pragma mark - Offscreen cells
@ -315,18 +263,47 @@ using namespace storage;
- (void)configAllMapsView
{
self.showAllMapsView = YES;
auto const & s = GetFramework().Storage();
TCountriesVec downloadedChildren;
TCountriesVec availableChildren;
TCountryId const parentCountryId = self.parentCountryId.UTF8String;
s.GetChildrenInGroups(parentCountryId, downloadedChildren, availableChildren);
if (availableChildren.empty())
if (self.mode == DownloaderMode::Downloaded)
{
Storage::UpdateInfo updateInfo{};
s.GetUpdateInfo(parentCountryId, updateInfo);
self.showAllMapsButtons = updateInfo.m_numberOfMwmFilesToUpdate != 0;
if (self.showAllMapsButtons)
{
self.allMapsButton.hidden = NO;
[self.allMapsButton
setTitle:[NSString stringWithFormat:kAllMapsLabelFormat, kUpdateAllTitle,
formattedSize(updateInfo.m_totalUpdateSizeInBytes)]
forState:UIControlStateNormal];
self.allMapsCancelButton.hidden = YES;
}
}
else if (parentCountryId != s.GetRootId())
{
TCountriesVec queuedChildren;
s.GetQueuedChildren(parentCountryId, queuedChildren);
if (!queuedChildren.empty())
if (queuedChildren.empty())
{
TCountriesVec downloadedChildren;
TCountriesVec availableChildren;
s.GetChildrenInGroups(parentCountryId, downloadedChildren, availableChildren, true /* keepAvailableChildren */);
self.showAllMapsButtons = downloadedChildren.size() != availableChildren.size();
if (self.showAllMapsButtons)
{
NodeAttrs nodeAttrs;
s.GetNodeAttrs(parentCountryId, nodeAttrs);
self.allMapsButton.hidden = NO;
[self.allMapsButton
setTitle:[NSString stringWithFormat:kAllMapsLabelFormat, kDownloadAllActionTitle,
formattedSize(nodeAttrs.m_mwmSize -
nodeAttrs.m_localMwmSize)]
forState:UIControlStateNormal];
self.allMapsCancelButton.hidden = YES;
}
}
else
{
TMwmSize queuedSize = 0;
for (TCountryId const & countryId : queuedChildren)
@ -335,29 +312,19 @@ using namespace storage;
s.GetNodeAttrs(countryId, nodeAttrs);
queuedSize += nodeAttrs.m_mwmSize;
}
self.allMapsLabel.text =
[NSString stringWithFormat:kAllMapsLabelFormat, kDownloadingTitle,
@(queuedChildren.size()), formattedSize(queuedSize)];
[self.allMapsButton setTitle:kCancelAllTitle forState:UIControlStateNormal];
return;
self.showAllMapsButtons = YES;
self.allMapsButton.hidden = YES;
self.allMapsCancelButton.hidden = NO;
[self.allMapsCancelButton
setTitle:[NSString stringWithFormat:kAllMapsLabelFormat, kCancelAllTitle,
formattedSize(queuedSize)]
forState:UIControlStateNormal];
}
}
else
{
NodeAttrs nodeAttrs;
s.GetNodeAttrs(parentCountryId, nodeAttrs);
uint32_t remoteMWMCounter = nodeAttrs.m_mwmCounter - nodeAttrs.m_localMwmCounter;
if (remoteMWMCounter != 0)
{
self.allMapsLabel.text =
[NSString stringWithFormat:kAllMapsLabelFormat, kMapsTitle, @(remoteMWMCounter),
formattedSize(nodeAttrs.m_mwmSize - nodeAttrs.m_localMwmSize)];
[self.allMapsButton setTitle:kDownloaAllTitle forState:UIControlStateNormal];
return;
}
self.showAllMapsButtons = NO;
}
self.showAllMapsView = NO;
}
- (void)refreshAllMapsView
@ -367,7 +334,7 @@ using namespace storage;
- (void)refreshAllMapsViewForOffset:(CGFloat)scrollOffset
{
if (!self.showAllMapsView)
if (!self.showAllMapsButtons)
return;
BOOL const hide = (scrollOffset >= self.lastScrollOffset) && !equalScreenDimensions(scrollOffset, 0.0);
self.lastScrollOffset = scrollOffset;
@ -393,7 +360,7 @@ using namespace storage;
{
self.skipCountryEventProcessing = YES;
TCountryId const parentCountryId = self.parentCountryId.UTF8String;
if (parentCountryId == GetFramework().Storage().GetRootId())
if (self.mode == DownloaderMode::Downloaded)
{
[Statistics logEvent:kStatDownloaderMapAction
withParameters:@{
@ -406,36 +373,37 @@ using namespace storage;
}
else
{
NSString * allMapsButtonTitle = [self.allMapsButton titleForState:UIControlStateNormal];
if ([allMapsButtonTitle isEqualToString:kDownloaAllTitle])
{
[Statistics logEvent:kStatDownloaderMapAction
withParameters:@{
kStatAction : kStatDownload,
kStatIsAuto : kStatNo,
kStatFrom : kStatDownloader,
kStatScenario : kStatDownloadGroup
}];
[MWMStorage downloadNode:parentCountryId
alertController:self.alertController
onSuccess:nil];
}
else if ([allMapsButtonTitle isEqualToString:kCancelAllTitle])
{
[Statistics logEvent:kStatDownloaderMapAction
withParameters:@{
kStatAction : kStatCancel,
kStatIsAuto : kStatNo,
kStatFrom : kStatDownloader,
kStatScenario : kStatDownloadGroup
}];
[MWMStorage cancelDownloadNode:parentCountryId];
}
[Statistics logEvent:kStatDownloaderMapAction
withParameters:@{
kStatAction : kStatDownload,
kStatIsAuto : kStatNo,
kStatFrom : kStatDownloader,
kStatScenario : kStatDownloadGroup
}];
[MWMStorage downloadNode:parentCountryId
alertController:self.alertController
onSuccess:nil];
}
self.skipCountryEventProcessing = NO;
[self processCountryEvent:parentCountryId];
}
- (IBAction)allMapsCancelAction
{
self.skipCountryEventProcessing = YES;
[Statistics logEvent:kStatDownloaderMapAction
withParameters:@{
kStatAction : kStatCancel,
kStatIsAuto : kStatNo,
kStatFrom : kStatDownloader,
kStatScenario : kStatDownloadGroup
}];
TCountryId const parentCountryId = self.parentCountryId.UTF8String;
[MWMStorage cancelDownloadNode:parentCountryId];
self.skipCountryEventProcessing = NO;
[self processCountryEvent:parentCountryId];
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
@ -444,9 +412,10 @@ using namespace storage;
NSString * identifier = [self.dataSource cellIdentifierForIndexPath:indexPath];
if ([identifier isEqualToString:kLargeCountryCellIdentifier])
{
MWMBaseMapDownloaderViewController * vc = [self.storyboard instantiateViewControllerWithIdentifier:@"MWMBaseMapDownloaderViewController"];
vc.parentCountryId = [self.dataSource countryIdForIndexPath:indexPath];
[MWMSegue segueFrom:self to:vc];
NSAssert(self.dataSource != nil, @"Datasource is nil.");
NSString * countyId = [self.dataSource countryIdForIndexPath:indexPath];
NSAssert(countyId != nil, @"CountryId is nil.");
[self openNodeSubtree:countyId.UTF8String];
}
else
{
@ -475,12 +444,16 @@ using namespace storage;
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.dataSource isButtonCell:indexPath.section])
return [MWMMapDownloaderButtonTableViewCell estimatedHeight];
Class<MWMMapDownloaderTableViewCellProtocol> cellClass = NSClassFromString([self.dataSource cellIdentifierForIndexPath:indexPath]);
return [cellClass estimatedHeight];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if ([self.dataSource isButtonCell:section])
return 36.0;
return 28.0;
}
@ -496,10 +469,194 @@ using namespace storage;
if (sender.state != UIGestureRecognizerStateBegan)
return;
NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint:[sender locationInView:self.tableView]];
if (indexPath)
if (indexPath && ![self.dataSource isButtonCell:indexPath.section])
[self showActionSheetForRowAtIndexPath:indexPath];
}
#pragma mark - Action Sheet
- (void)showActionSheetForRowAtIndexPath:(NSIndexPath *)indexPath
{
auto const & s = GetFramework().Storage();
NodeAttrs nodeAttrs;
NSAssert(self.dataSource != nil, @"Datasource is nil.");
NSString * countyId = [self.dataSource countryIdForIndexPath:indexPath];
NSAssert(countyId != nil, @"CountryId is nil.");
m_actionSheetId = countyId.UTF8String;
s.GetNodeAttrs(m_actionSheetId, nodeAttrs);
ActionButtons buttons = NoAction;
switch (nodeAttrs.m_status)
{
case NodeStatus::Undefined:
break;
case NodeStatus::NotDownloaded:
buttons |= DownloadAction;
break;
case NodeStatus::Downloading:
case NodeStatus::InQueue:
buttons |= CancelDownloadAction;
break;
case NodeStatus::OnDiskOutOfDate:
buttons |= ShowOnMapAction;
buttons |= UpdateAction;
buttons |= DeleteAction;
break;
case NodeStatus::OnDisk:
buttons |= ShowOnMapAction;
buttons |= DeleteAction;
break;
case NodeStatus::Partly:
buttons |= DownloadAction;
buttons |= DeleteAction;
break;
case NodeStatus::Error:
buttons |= RetryDownloadAction;
if (nodeAttrs.m_localMwmCounter != 0)
buttons |= DeleteAction;
break;
}
NSAssert(buttons != NoAction, @"No action buttons defined.");
if (buttons == NoAction)
return;
UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIView * cellSuperView = cell.superview;
if (!cellSuperView)
return;
NSString * title = @(nodeAttrs.m_nodeLocalName.c_str());
BOOL const isMultiParent = (nodeAttrs.m_parentInfo.size() > 1);
NSString * message = (self.dataSource.isParentRoot || isMultiParent)
? nil
: @(nodeAttrs.m_parentInfo[0].m_localName.c_str());
if (isIOS7)
{
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:title
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[self addButtons:buttons toActionComponent:actionSheet];
[actionSheet showFromRect:cell.frame inView:cellSuperView animated:YES];
}
else
{
UIAlertController * alertController =
[UIAlertController alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleActionSheet];
UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:indexPath];
alertController.popoverPresentationController.sourceView = cell;
alertController.popoverPresentationController.sourceRect = cell.bounds;
[self addButtons:buttons toActionComponent:alertController];
[self presentViewController:alertController animated:YES completion:nil];
}
}
- (void)addButtons:(ActionButtons)buttons toActionComponent:(id)component
{
UIActionSheet * actionSheet = nil;
UIAlertController * alertController = nil;
if ([component isKindOfClass:[UIActionSheet class]])
actionSheet = component;
else if ([component isKindOfClass:[UIAlertController class]])
alertController = component;
if (buttons & ShowOnMapAction)
{
[actionSheet addButtonWithTitle:kShowOnMapActionTitle];
UIAlertAction * action = [UIAlertAction actionWithTitle:kShowOnMapActionTitle
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{ [self showNode:self->m_actionSheetId]; }];
[alertController addAction:action];
}
auto const & s = GetFramework().Storage();
if (buttons & DownloadAction)
{
NodeAttrs nodeAttrs;
s.GetNodeAttrs(m_actionSheetId, nodeAttrs);
NSString * prefix = nodeAttrs.m_mwmCounter == 1 ? kDownloadActionTitle : kDownloadAllActionTitle;
NSString * title = [NSString stringWithFormat:kAllMapsLabelFormat, prefix,
formattedSize(nodeAttrs.m_mwmSize - nodeAttrs.m_localMwmSize)];
[actionSheet addButtonWithTitle:title];
UIAlertAction * action = [UIAlertAction actionWithTitle:title
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{ [self downloadNode:self->m_actionSheetId]; }];
[alertController addAction:action];
}
if (buttons & UpdateAction)
{
TCountriesVec downloadedChildren;
TCountriesVec availableChildren;
s.GetChildrenInGroups(m_actionSheetId, downloadedChildren, availableChildren);
TMwmSize updateSize = 0;
for (TCountryId const & countryId : downloadedChildren)
{
NodeAttrs nodeAttrs;
s.GetNodeAttrs(countryId, nodeAttrs);
if (nodeAttrs.m_status == NodeStatus::OnDiskOutOfDate)
updateSize += nodeAttrs.m_mwmSize;
}
NSString * title = [NSString stringWithFormat:kAllMapsLabelFormat, kUpdateActionTitle,
formattedSize(updateSize)];
[actionSheet addButtonWithTitle:title];
UIAlertAction * action = [UIAlertAction actionWithTitle:title
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{ [self updateNode:self->m_actionSheetId]; }];
[alertController addAction:action];
}
if (buttons & CancelDownloadAction)
{
[actionSheet addButtonWithTitle:kCancelDownloadActionTitle];
actionSheet.destructiveButtonIndex = actionSheet.numberOfButtons - 1;
UIAlertAction * action = [UIAlertAction actionWithTitle:kCancelDownloadActionTitle
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action)
{ [self cancelNode:self->m_actionSheetId]; }];
[alertController addAction:action];
}
if (buttons & RetryDownloadAction)
{
[actionSheet addButtonWithTitle:kRetryActionTitle];
UIAlertAction * action = [UIAlertAction actionWithTitle:kRetryActionTitle
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action)
{ [self retryDownloadNode:self->m_actionSheetId]; }];
[alertController addAction:action];
}
if (buttons & DeleteAction)
{
[actionSheet addButtonWithTitle:kDeleteActionTitle];
actionSheet.destructiveButtonIndex = actionSheet.numberOfButtons - 1;
UIAlertAction * action = [UIAlertAction actionWithTitle:kDeleteActionTitle
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction * action)
{ [self deleteNode:self->m_actionSheetId]; }];
[alertController addAction:action];
}
if (!IPAD)
{
[actionSheet addButtonWithTitle:kCancelActionTitle];
actionSheet.cancelButtonIndex = actionSheet.numberOfButtons - 1;
}
UIAlertAction * action = [UIAlertAction actionWithTitle:kCancelActionTitle
style:UIAlertActionStyleCancel
handler:nil];
[alertController addAction:action];
}
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
@ -510,18 +667,42 @@ using namespace storage;
return;
}
NSString * btnTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([btnTitle hasPrefix:kDownloadActionTitle])
[self downloadNode:m_actionSheetId];
else if ([btnTitle isEqualToString:kDeleteActionTitle])
[self deleteNode:m_actionSheetId];
else if ([btnTitle isEqualToString:kUpdateActionTitle])
[self updateNode:m_actionSheetId];
else if ([btnTitle isEqualToString:kShowActionTitle])
if ([btnTitle containsString:kShowOnMapActionTitle])
[self showNode:m_actionSheetId];
else if ([btnTitle containsString:kDownloadAllActionTitle])
[self downloadNode:m_actionSheetId];
else if ([btnTitle containsString:kDownloadActionTitle])
[self downloadNode:m_actionSheetId];
else if ([btnTitle containsString:kUpdateActionTitle])
[self updateNode:m_actionSheetId];
else if ([btnTitle containsString:kCancelDownloadActionTitle])
[self cancelNode:m_actionSheetId];
else if ([btnTitle containsString:kRetryActionTitle])
[self retryDownloadNode:m_actionSheetId];
else if ([btnTitle containsString:kDeleteActionTitle])
[self deleteNode:m_actionSheetId];
}
#pragma mark - Countries tree(s) navigation
- (void)openAvailableMaps
{
BOOL const isParentRoot = [self.parentCountryId isEqualToString:@(GetFramework().Storage().GetRootId().c_str())];
NSString * identifier = isParentRoot ? kControllerIdentifier : kBaseControllerIdentifier;
MWMBaseMapDownloaderViewController * vc = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
[vc setParentCountryId:self.parentCountryId mode:DownloaderMode::Available];
[MWMSegue segueFrom:self to:vc];
}
#pragma mark - MWMMapDownloaderProtocol
- (void)openNodeSubtree:(storage::TCountryId const &)countryId
{
MWMBaseMapDownloaderViewController * vc = [self.storyboard instantiateViewControllerWithIdentifier:kBaseControllerIdentifier];
[vc setParentCountryId:@(countryId.c_str()) mode:self.mode];
[MWMSegue segueFrom:self to:vc];
}
- (void)downloadNode:(storage::TCountryId const &)countryId
{
[Statistics logEvent:kStatDownloaderMapAction
@ -609,6 +790,15 @@ using namespace storage;
return UIStatusBarStyleLightContent;
}
#pragma mark - Configuration
- (void)setParentCountryId:(NSString *)parentId mode:(DownloaderMode)mode
{
self.defaultDataSource = [[MWMMapDownloaderDefaultDataSource alloc] initForRootCountryId:parentId
delegate:self
mode:mode];
}
#pragma mark - Properties
- (void)setTableView:(UITableView *)tableView
@ -618,20 +808,20 @@ using namespace storage;
self.dataSource = self.defaultDataSource;
}
- (void)setShowAllMapsView:(BOOL)showAllMapsView
- (void)setShowAllMapsButtons:(BOOL)showAllMapsButtons
{
_showAllMapsView = showAllMapsView;
self.allMapsView.hidden = !showAllMapsView;
_showAllMapsButtons = showAllMapsButtons;
self.allMapsView.hidden = !showAllMapsButtons;
}
- (NSString *)parentCountryId
{
return [self.dataSource parentCountryId];
return self.dataSource.parentCountryId;
}
- (void)setParentCountryId:(NSString *)parentId
- (DownloaderMode)mode
{
self.defaultDataSource = [[MWMMapDownloaderDefaultDataSource alloc] initForRootCountryId:parentId delegate:self];
return self.dataSource.mode;
}
- (void)setDataSource:(MWMMapDownloaderDataSource *)dataSource
@ -649,8 +839,8 @@ using namespace storage;
- (void)reloadData
{
MWMMapDownloaderDefaultDataSource * defaultDataSource = self.defaultDataSource;
[defaultDataSource reload];
if ([self.dataSource isEqual:defaultDataSource])
[defaultDataSource load];
if (self.dataSource == defaultDataSource)
[self reloadTable];
}
@ -658,27 +848,16 @@ using namespace storage;
{
[self.cellHeightCache removeAllObjects];
MWMMapDownloaderDataSource * dataSource = self.dataSource;
UITableView * tableView = self.tableView;
if (self.forceFullReload || dataSource.needFullReload)
{
self.forceFullReload = NO;
// If these methods are not called, tableView will not call tableView:cellForRowAtIndexPath:
[tableView setNeedsLayout];
[tableView layoutIfNeeded];
// If these methods are not called, tableView will not call tableView:cellForRowAtIndexPath:
[tableView setNeedsLayout];
[tableView layoutIfNeeded];
[tableView reloadData];
[tableView reloadData];
// If these methods are not called, tableView will not display new cells
[tableView setNeedsLayout];
[tableView layoutIfNeeded];
}
else
{
NSMutableIndexSet * reloadSections = dataSource.reloadSections;
if (reloadSections.count)
[tableView reloadSections:reloadSections withRowAnimation:UITableViewRowAnimationAutomatic];
}
// If these methods are not called, tableView will not display new cells
[tableView setNeedsLayout];
[tableView layoutIfNeeded];
}
@end

View file

@ -2,6 +2,7 @@
@protocol MWMMapDownloaderProtocol <NSObject>
- (void)openNodeSubtree:(storage::TCountryId const &)countryId;
- (void)downloadNode:(storage::TCountryId const &)countryId;
- (void)retryDownloadNode:(storage::TCountryId const &)countryId;
- (void)updateNode:(storage::TCountryId const &)countryId;

View file

@ -0,0 +1,8 @@
namespace mwm
{
enum class DownloaderMode
{
Downloaded,
Available
};
} // namespace mwm

View file

@ -2,6 +2,7 @@
#import "MWMMapDownloaderExtendedDataSource.h"
#import "MWMMapDownloaderSearchDataSource.h"
#import "MWMMapDownloaderViewController.h"
#import "MWMNoMapsViewController.h"
#import "UIColor+MapsMeColor.h"
#import "UIKitCategories.h"
@ -9,6 +10,11 @@
#include "storage/downloader_search_params.hpp"
namespace
{
NSString * const kNoMapsSegue = @"MapDownloaderEmbedNoMapsSegue";
} // namespace
using namespace storage;
@interface MWMBaseMapDownloaderViewController ()
@ -18,14 +24,25 @@ using namespace storage;
@property (nonatomic) MWMMapDownloaderDataSource * dataSource;
@property (nonatomic) MWMMapDownloaderDataSource * defaultDataSource;
@property (nonatomic, readonly) NSString * parentCountryId;
@property (nonatomic, readonly) mwm::DownloaderMode mode;
@property (nonatomic) BOOL showAllMapsButtons;
- (void)configViews;
- (void)openAvailableMaps;
- (void)reloadTable;
@end
@interface MWMMapDownloaderViewController () <UISearchBarDelegate, UIScrollViewDelegate>
@interface MWMMapDownloaderViewController () <UISearchBarDelegate, UIScrollViewDelegate, MWMNoMapsViewControllerProtocol>
@property (weak, nonatomic) IBOutlet UIView * statusBarBackground;
@property (weak, nonatomic) IBOutlet UISearchBar * searchBar;
@property (weak, nonatomic) IBOutlet UIView * noMapsContainer;
@property (nonatomic) MWMNoMapsViewController * noMapsController;
@property (nonatomic) MWMMapDownloaderDataSource * searchDataSource;
@ -53,23 +70,39 @@ using namespace storage;
- (void)backTap
{
[self.navigationController popToRootViewControllerAnimated:YES];
NSArray<UIViewController *> * viewControllers = self.navigationController.viewControllers;
UIViewController * previousViewController = viewControllers[viewControllers.count - 2];
if ([previousViewController isKindOfClass:[MWMBaseMapDownloaderViewController class]])
[self.navigationController popViewControllerAnimated:YES];
else
[self.navigationController popToRootViewControllerAnimated:YES];
}
#pragma mark - All Maps Action
- (void)configAllMapsView
- (void)configViews
{
[super configViews];
[self checkAndConfigNoMapsView];
}
#pragma mark - No Maps
- (void)checkAndConfigNoMapsView
{
self.showAllMapsView = NO;
auto const & s = GetFramework().Storage();
Storage::UpdateInfo updateInfo{};
if (!s.GetUpdateInfo(s.GetRootId(), updateInfo) || updateInfo.m_numberOfMwmFilesToUpdate == 0)
if (![self.parentCountryId isEqualToString:@(s.GetRootId().c_str())])
return;
self.allMapsLabel.text =
[NSString stringWithFormat:@"%@: %@ (%@)", L(@"downloader_outdated_maps"),
@(updateInfo.m_numberOfMwmFilesToUpdate),
formattedSize(updateInfo.m_totalUpdateSizeInBytes)];
self.showAllMapsView = YES;
if (self.mode == mwm::DownloaderMode::Available || s.HaveDownloadedCountries())
{
[self configAllMapsView];
self.tableView.hidden = NO;
self.noMapsContainer.hidden = YES;
}
else
{
self.showAllMapsButtons = NO;
self.tableView.hidden = YES;
self.noMapsContainer.hidden = NO;
}
}
#pragma mark - UISearchBarDelegate
@ -142,11 +175,39 @@ using namespace storage;
};
}
#pragma mark - Properties
#pragma mark - UIScrollViewDelegate
- (void)setParentCountryId:(NSString *)parentId
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
self.defaultDataSource = [[MWMMapDownloaderExtendedDataSource alloc] initForRootCountryId:parentId delegate:self];
[self.searchBar resignFirstResponder];
}
#pragma mark - MWMNoMapsViewControllerProtocol
- (void)handleDownloadMapsAction
{
[self openAvailableMaps];
}
#pragma mark - Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[super prepareForSegue:segue sender:sender];
if ([segue.identifier isEqualToString:kNoMapsSegue])
{
self.noMapsController = segue.destinationViewController;
self.noMapsController.delegate = self;
}
}
#pragma mark - Configuration
- (void)setParentCountryId:(NSString *)parentId mode:(mwm::DownloaderMode)mode
{
self.defaultDataSource = [[MWMMapDownloaderExtendedDataSource alloc] initForRootCountryId:parentId
delegate:self
mode:mode];
}
@end

View file

@ -1,5 +1,6 @@
#import "LocationManager.h"
#import "LocationPredictor.h"
#import "MWMMapDownloaderTypes.h"
#import "MWMViewController.h"
#import <MyTargetSDKCorp/MTRGNativeAppwallAd.h>
@ -33,7 +34,7 @@ namespace search { struct AddressInfo; }
- (void)openMigration;
- (void)openBookmarks;
- (void)openMapsDownloader;
- (void)openMapsDownloader:(mwm::DownloaderMode)mode;
- (void)openEditor;
- (void)refreshAd;

View file

@ -548,10 +548,10 @@ NSString * const kUDViralAlertWasShown = @"ViralAlertWasShown";
[self.navigationController pushViewController:vc animated:YES];
}
- (void)openMapsDownloader
- (void)openMapsDownloader:(mwm::DownloaderMode)mode
{
[Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"downloader"];
[self performSegueWithIdentifier:kDownloaderSegue sender:self];
[self performSegueWithIdentifier:kDownloaderSegue sender:@(static_cast<NSInteger>(mode))];
}
- (void)openEditor
@ -844,7 +844,8 @@ NSString * const kUDViralAlertWasShown = @"ViralAlertWasShown";
else if ([segue.identifier isEqualToString:kDownloaderSegue])
{
MWMMapDownloaderViewController * dvc = segue.destinationViewController;
dvc.parentCountryId = @(GetFramework().Storage().GetRootId().c_str());
NSNumber * mode = sender;
[dvc setParentCountryId:@(GetFramework().Storage().GetRootId().c_str()) mode:static_cast<mwm::DownloaderMode>(mode.integerValue)];
}
else if ([segue.identifier isEqualToString:kMap2FBLoginSegue])
{

View file

@ -179,7 +179,7 @@ using namespace storage;
if ([segue.identifier isEqualToString:kDownloaderSegue])
{
MWMMapDownloaderViewController * dvc = segue.destinationViewController;
dvc.parentCountryId = @(GetFramework().Storage().GetRootId().c_str());
[dvc setParentCountryId:@(GetFramework().Storage().GetRootId().c_str()) mode:mwm::DownloaderMode::Downloaded];
}
}

View file

@ -3,6 +3,9 @@
- (void)showBackButton;
- (void)backTap;
- (UIBarButtonItem *)buttonWithImage:(UIImage *)image action:(SEL)action;
- (NSArray<UIBarButtonItem *> *)alignedNavBarButtonItems:(NSArray<UIBarButtonItem *> *)items;
@property (nonatomic, readonly) UIStoryboard * mainStoryboard;
@end

View file

@ -4,42 +4,46 @@
namespace
{
CGFloat constexpr kButtonExtraWidth = 16.0;
}
} // namespace
@implementation UIViewController (Navigation)
- (UIBarButtonItem *)negativeSpacer
{
UIBarButtonItem * spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
UIBarButtonItem * spacer =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
spacer.width = -kButtonExtraWidth;
return spacer;
}
- (UIBarButtonItem *)buttonWithImage:(UIImage *)image action:(SEL)action
{
CGSize const buttonSize = {image.size.width + kButtonExtraWidth, image.size.height};
UIButton * button = [[UIButton alloc] initWithFrame:{{}, buttonSize}];
[button setImage:image forState:UIControlStateNormal];
[button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
return [[UIBarButtonItem alloc] initWithCustomView:button];
}
- (NSArray<UIBarButtonItem *> *)alignedNavBarButtonItems:(NSArray<UIBarButtonItem *> *)items
{
return [@[ [self negativeSpacer] ] arrayByAddingObjectsFromArray:items];
}
- (UIBarButtonItem *)backButton
{
UIImage * backImage = [UIImage imageNamed:@"ic_nav_bar_back"];
UIImage * highlightedImage = [UIImage imageNamed:@"ic_nav_bar_back_press"];
CGSize const buttonSize = {backImage.size.width + kButtonExtraWidth, backImage.size.height};
UIButton * button = [[UIButton alloc] initWithFrame:{{}, buttonSize}];
[button setImage:backImage forState:UIControlStateNormal];
[button setImage:highlightedImage forState:UIControlStateHighlighted];
[button addTarget:self action:@selector(backTap) forControlEvents:UIControlEventTouchUpInside];
return [[UIBarButtonItem alloc] initWithCustomView:button];
return [self buttonWithImage:[UIImage imageNamed:@"ic_nav_bar_back"] action:@selector(backTap)];
}
- (void)showBackButton
{
self.navigationItem.leftBarButtonItems = @[[self negativeSpacer], [self backButton]];
self.navigationItem.leftBarButtonItems = [self alignedNavBarButtonItems:@[ [self backButton] ]];
}
- (void)backTap
{
[self.navigationController popViewControllerAnimated:YES];
}
- (void)backTap { [self.navigationController popViewControllerAnimated:YES]; }
- (UIStoryboard *)mainStoryboard
{
return [UIStoryboard storyboardWithName:@"Mapsme" bundle:nil];
}
- (UIStoryboard *)mainStoryboard { return [UIStoryboard storyboardWithName:@"Mapsme" bundle:nil]; }
@end

View file

@ -2,22 +2,25 @@
"images" : [
{
"idiom" : "universal",
"filename" : "ic_nav_bar_back_press.png",
"filename" : "ic_folder.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_nav_bar_back_press@2x.png",
"filename" : "ic_folder@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_nav_bar_back_press@3x.png",
"filename" : "ic_folder@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

View file

@ -19,8 +19,5 @@
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 B

View file

@ -262,6 +262,10 @@
34DCDE3B1C75CE1F00652CAC /* MWMOpeningHoursDeleteScheduleTableViewCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 347FD85A1C60B2CE002FB65E /* MWMOpeningHoursDeleteScheduleTableViewCell.mm */; };
34DDD5341BFDB0B600407F2F /* MWMMapDownloaderViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 342AF0DF1BE24E9A0016F3AE /* MWMMapDownloaderViewController.mm */; };
34DDD5351BFDB0C600407F2F /* MWMBaseMapDownloaderViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 341223BA1BEB58FA007227E9 /* MWMBaseMapDownloaderViewController.mm */; };
34E0EECE1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34E0EECC1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.mm */; };
34E0EECF1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34E0EECC1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.mm */; };
34E0EED01CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 34E0EECD1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.xib */; };
34E0EED11CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 34E0EECD1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.xib */; };
34E273211C737A4100463965 /* MWMMigrationViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34E273201C737A4100463965 /* MWMMigrationViewController.mm */; };
34E273221C737A4100463965 /* MWMMigrationViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34E273201C737A4100463965 /* MWMMigrationViewController.mm */; };
34E273251C73876500463965 /* MWMMigrationView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34E273241C73876500463965 /* MWMMigrationView.mm */; };
@ -1140,6 +1144,11 @@
34D15BA61BD8F93C00C8BCBE /* AddSetTableViewCell.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AddSetTableViewCell.mm; sourceTree = "<group>"; };
34D15BA71BD8F93C00C8BCBE /* AddSetTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AddSetTableViewCell.xib; sourceTree = "<group>"; };
34DCDE3D1C76195F00652CAC /* MWMMapDownloaderProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMMapDownloaderProtocol.h; sourceTree = "<group>"; };
34E0EECA1CC4F36B008E4919 /* MWMMapDownloaderTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMMapDownloaderTypes.h; sourceTree = "<group>"; };
34E0EECB1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMMapDownloaderButtonTableViewCell.h; sourceTree = "<group>"; };
34E0EECC1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMMapDownloaderButtonTableViewCell.mm; sourceTree = "<group>"; };
34E0EECD1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MWMMapDownloaderButtonTableViewCell.xib; sourceTree = "<group>"; };
34E0EED21CC51B70008E4919 /* MWMMapDownloaderTableViewCellProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMMapDownloaderTableViewCellProtocol.h; sourceTree = "<group>"; };
34E2731F1C737A4100463965 /* MWMMigrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMMigrationViewController.h; sourceTree = "<group>"; };
34E273201C737A4100463965 /* MWMMigrationViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMMigrationViewController.mm; sourceTree = "<group>"; };
34E273231C73876500463965 /* MWMMigrationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMMigrationView.h; sourceTree = "<group>"; };
@ -1890,6 +1899,7 @@
341F99C81C6B1165001C67B8 /* Cells */ = {
isa = PBXGroup;
children = (
34E0EED21CC51B70008E4919 /* MWMMapDownloaderTableViewCellProtocol.h */,
341F99C91C6B1165001C67B8 /* MWMMapDownloaderLargeCountryTableViewCell.h */,
341F99CA1C6B1165001C67B8 /* MWMMapDownloaderLargeCountryTableViewCell.mm */,
341F99CB1C6B1165001C67B8 /* MWMMapDownloaderLargeCountryTableViewCell.xib */,
@ -1902,6 +1912,9 @@
341F99D21C6B1165001C67B8 /* MWMMapDownloaderTableViewCell.h */,
341F99D31C6B1165001C67B8 /* MWMMapDownloaderTableViewCell.mm */,
341F99D41C6B1165001C67B8 /* MWMMapDownloaderTableViewCell.xib */,
34E0EECB1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.h */,
34E0EECC1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.mm */,
34E0EECD1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.xib */,
);
path = Cells;
sourceTree = "<group>";
@ -1925,6 +1938,7 @@
isa = PBXGroup;
children = (
3418CEAB1CBF9D7700641B25 /* NoMaps */,
34E0EECA1CC4F36B008E4919 /* MWMMapDownloaderTypes.h */,
34DCDE3D1C76195F00652CAC /* MWMMapDownloaderProtocol.h */,
341223B91BEB58FA007227E9 /* MWMBaseMapDownloaderViewController.h */,
341223BA1BEB58FA007227E9 /* MWMBaseMapDownloaderViewController.mm */,
@ -3338,6 +3352,7 @@
347BAC691B733D540010FF78 /* MWMPedestrianShareAlert.xib in Resources */,
F6FF2E2B1B8C5C020063FD1F /* MWMNextTurnPanel.xib in Resources */,
FAF30A95173AB23900818BF6 /* 07_roboto_medium.ttf in Resources */,
34E0EED01CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3482,6 +3497,7 @@
6741A99D1BF340DE002C974C /* MWMPedestrianShareAlert.xib in Resources */,
6741A99E1BF340DE002C974C /* MWMNextTurnPanel.xib in Resources */,
6741A99F1BF340DE002C974C /* 07_roboto_medium.ttf in Resources */,
34E0EED11CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -3583,6 +3599,7 @@
34CFFE8B1B7DE6FD009D0C9F /* MWMSearchManager.mm in Sources */,
34ABA62C1C2D57D500FE1BEC /* MWMInputPasswordValidator.mm in Sources */,
34ABA6161C2D185C00FE1BEC /* MWMAuthorizationOSMLoginViewController.mm in Sources */,
34E0EECE1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.mm in Sources */,
3492CC121C6DF00E0057D8E8 /* (null) in Sources */,
F6BBF2C61B4FFB72000CF8E2 /* MWMLocationAlert.mm in Sources */,
F66A8FB01B09F268001B9C97 /* MWMPlacePage.mm in Sources */,
@ -3799,6 +3816,7 @@
34ABA6171C2D185C00FE1BEC /* MWMAuthorizationOSMLoginViewController.mm in Sources */,
6741A9D01BF340DE002C974C /* MWMPlacePage.mm in Sources */,
3492CC131C6DF00F0057D8E8 /* (null) in Sources */,
34E0EECF1CC51B1D008E4919 /* MWMMapDownloaderButtonTableViewCell.mm in Sources */,
6741A9D21BF340DE002C974C /* MWMBookmarkDescriptionViewController.mm in Sources */,
3476B8CC1BFDCB6700874594 /* MWMTTSSettingsViewController.mm in Sources */,
6741A9D41BF340DE002C974C /* MWMAlertViewController.mm in Sources */,

View file

@ -1902,46 +1902,53 @@
<constraint firstAttribute="height" constant="1" id="6LI-Em-15P"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="5 Outdated Maps (108 MB)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="464" translatesAutoresizingMaskIntoConstraints="NO" id="VGz-7h-6K5">
<rect key="frame" x="16" y="14" width="444" height="17"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.54000000000000004" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GN0-2F-Ytz" customClass="MWMButton">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
<color key="backgroundColor" name="alternateSelectedControlColor" catalog="System" colorSpace="catalog"/>
<state key="normal" title="Update All">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular14"/>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
</userDefinedRuntimeAttributes>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GN0-2F-Ytz">
<rect key="frame" x="460" y="0.0" width="140" height="44"/>
<constraints>
<constraint firstAttribute="width" constant="140" id="ker-jb-D1t"/>
</constraints>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<state key="normal" title="Update All"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium17"/>
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="downloader_update_all_button"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMWhite"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="allMapsAction" destination="h4a-ne-bSJ" eventType="touchUpInside" id="swH-BL-Egj"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bQM-6x-WHa" customClass="MWMButton">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<state key="normal" title="Update All">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="red"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="allMapsCancelAction" destination="h4a-ne-bSJ" eventType="touchUpInside" id="UOO-Sn-8Cf"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="GN0-2F-Ytz" secondAttribute="bottom" id="1d7-Jm-x6G"/>
<constraint firstAttribute="trailing" secondItem="GN0-2F-Ytz" secondAttribute="trailing" id="Fla-om-Cu2"/>
<constraint firstAttribute="bottom" secondItem="bQM-6x-WHa" secondAttribute="bottom" id="GhH-Ej-y9d"/>
<constraint firstItem="GN0-2F-Ytz" firstAttribute="top" secondItem="st5-ZJ-F0A" secondAttribute="top" id="JFl-uF-Jcg"/>
<constraint firstItem="GN0-2F-Ytz" firstAttribute="leading" secondItem="VGz-7h-6K5" secondAttribute="trailing" id="MKo-d0-s9t"/>
<constraint firstItem="VGz-7h-6K5" firstAttribute="leading" secondItem="st5-ZJ-F0A" secondAttribute="leading" constant="16" id="NSY-0Y-fsn"/>
<constraint firstItem="0aj-pt-FjD" firstAttribute="leading" secondItem="st5-ZJ-F0A" secondAttribute="leading" id="T1h-9e-CHh"/>
<constraint firstItem="GN0-2F-Ytz" firstAttribute="centerY" secondItem="st5-ZJ-F0A" secondAttribute="centerY" id="TYj-uT-caw"/>
<constraint firstAttribute="trailing" secondItem="0aj-pt-FjD" secondAttribute="trailing" id="X27-uq-GY8"/>
<constraint firstItem="bQM-6x-WHa" firstAttribute="leading" secondItem="st5-ZJ-F0A" secondAttribute="leading" id="YLa-6K-Khm"/>
<constraint firstItem="0aj-pt-FjD" firstAttribute="top" secondItem="st5-ZJ-F0A" secondAttribute="top" id="k6u-bm-1dm"/>
<constraint firstItem="bQM-6x-WHa" firstAttribute="top" secondItem="st5-ZJ-F0A" secondAttribute="top" id="lgd-lj-2Qq"/>
<constraint firstItem="GN0-2F-Ytz" firstAttribute="leading" secondItem="st5-ZJ-F0A" secondAttribute="leading" id="nUN-rN-AXo"/>
<constraint firstAttribute="trailing" secondItem="bQM-6x-WHa" secondAttribute="trailing" id="pIt-FK-n43"/>
<constraint firstAttribute="height" constant="44" id="r0c-5a-Stj"/>
<constraint firstItem="VGz-7h-6K5" firstAttribute="centerY" secondItem="st5-ZJ-F0A" secondAttribute="centerY" id="r2v-H3-L2q"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
@ -1990,7 +1997,7 @@
<containerView hidden="YES" opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kXO-Oh-2vO" userLabel="No Maps Container View">
<rect key="frame" x="0.0" y="64" width="600" height="536"/>
<connections>
<segue destination="3el-Zi-2E4" kind="embed" id="ish-dC-mkH"/>
<segue destination="3el-Zi-2E4" kind="embed" identifier="MapDownloaderEmbedNoMapsSegue" id="ish-dC-mkH"/>
</connections>
</containerView>
</subviews>
@ -2020,9 +2027,11 @@
</userDefinedRuntimeAttributes>
</view>
<connections>
<outlet property="allMapsLabel" destination="VGz-7h-6K5" id="eoI-x5-VSc"/>
<outlet property="allMapsButton" destination="GN0-2F-Ytz" id="Oi0-99-SSP"/>
<outlet property="allMapsCancelButton" destination="bQM-6x-WHa" id="GhS-AQ-EZd"/>
<outlet property="allMapsView" destination="st5-ZJ-F0A" id="KAY-Rx-kCC"/>
<outlet property="allMapsViewBottomOffset" destination="wj3-ZU-xMA" id="jfn-W1-TEn"/>
<outlet property="noMapsContainer" destination="kXO-Oh-2vO" id="fpe-Gj-ZmD"/>
<outlet property="searchBar" destination="DPt-gs-efn" id="HS1-0c-JX8"/>
<outlet property="statusBarBackground" destination="Xxz-fq-71r" id="W1o-7P-C8n"/>
<outlet property="tableView" destination="CwW-x8-G3j" id="uIf-Yj-DiC"/>
@ -2071,45 +2080,53 @@
<constraint firstAttribute="height" constant="1" id="77N-Bp-ThF"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="14 Maps (291 MB)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="464" translatesAutoresizingMaskIntoConstraints="NO" id="ks9-BF-szs">
<rect key="frame" x="16" y="14" width="444" height="17"/>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="14"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.54000000000000004" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xL5-0u-TaG" customClass="MWMButton">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
<color key="backgroundColor" name="alternateSelectedControlColor" catalog="System" colorSpace="catalog"/>
<state key="normal" title="Download All">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular14"/>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
</userDefinedRuntimeAttributes>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xL5-0u-TaG">
<rect key="frame" x="460" y="0.0" width="140" height="44"/>
<constraints>
<constraint firstAttribute="width" constant="140" id="Fbl-8r-jNo"/>
</constraints>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<state key="normal" title="Download All"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium17"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
<userDefinedRuntimeAttribute type="string" keyPath="coloringName" value="MWMWhite"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="allMapsAction" destination="ccD-FK-8j5" eventType="touchUpInside" id="EtQ-2G-MEd"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MmB-HW-cD5" customClass="MWMButton">
<rect key="frame" x="0.0" y="0.0" width="600" height="44"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<state key="normal" title="Download All">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="red"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="allMapsCancelAction" destination="ccD-FK-8j5" eventType="touchUpInside" id="Wob-NQ-ZJX"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="C2D-Ac-wjh" firstAttribute="leading" secondItem="9vd-CW-37q" secondAttribute="leading" id="00a-wh-BaK"/>
<constraint firstItem="xL5-0u-TaG" firstAttribute="top" secondItem="9vd-CW-37q" secondAttribute="top" id="6ui-Df-HR9"/>
<constraint firstItem="xL5-0u-TaG" firstAttribute="centerY" secondItem="9vd-CW-37q" secondAttribute="centerY" id="8ea-Gk-AzX"/>
<constraint firstItem="ks9-BF-szs" firstAttribute="leading" secondItem="9vd-CW-37q" secondAttribute="leading" constant="16" id="AhA-nC-yx9"/>
<constraint firstItem="MmB-HW-cD5" firstAttribute="leading" secondItem="9vd-CW-37q" secondAttribute="leading" id="Dh1-Fr-eWw"/>
<constraint firstAttribute="height" constant="44" id="Dow-HV-Frg"/>
<constraint firstItem="ks9-BF-szs" firstAttribute="centerY" secondItem="9vd-CW-37q" secondAttribute="centerY" id="KfJ-Rr-IJu"/>
<constraint firstItem="xL5-0u-TaG" firstAttribute="leading" secondItem="ks9-BF-szs" secondAttribute="trailing" id="UiT-gI-4fB"/>
<constraint firstItem="xL5-0u-TaG" firstAttribute="leading" secondItem="9vd-CW-37q" secondAttribute="leading" id="EdJ-xv-Ddl"/>
<constraint firstAttribute="bottom" secondItem="MmB-HW-cD5" secondAttribute="bottom" id="M2K-ym-QIN"/>
<constraint firstAttribute="trailing" secondItem="MmB-HW-cD5" secondAttribute="trailing" id="Qpf-le-AUb"/>
<constraint firstAttribute="trailing" secondItem="C2D-Ac-wjh" secondAttribute="trailing" id="ZvS-18-Itc"/>
<constraint firstItem="C2D-Ac-wjh" firstAttribute="top" secondItem="9vd-CW-37q" secondAttribute="top" id="aCR-gV-D3e"/>
<constraint firstAttribute="trailing" secondItem="xL5-0u-TaG" secondAttribute="trailing" id="gm9-AZ-44g"/>
<constraint firstAttribute="bottom" secondItem="xL5-0u-TaG" secondAttribute="bottom" id="rd1-SA-czc"/>
<constraint firstItem="MmB-HW-cD5" firstAttribute="top" secondItem="9vd-CW-37q" secondAttribute="top" id="xAU-rg-nW4"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
@ -2168,7 +2185,7 @@
</view>
<connections>
<outlet property="allMapsButton" destination="xL5-0u-TaG" id="09K-th-orY"/>
<outlet property="allMapsLabel" destination="ks9-BF-szs" id="fWQ-TU-r6w"/>
<outlet property="allMapsCancelButton" destination="MmB-HW-cD5" id="wsr-lk-f32"/>
<outlet property="allMapsView" destination="9vd-CW-37q" id="XZs-Bj-AmZ"/>
<outlet property="allMapsViewBottomOffset" destination="Vzi-ku-bUf" id="jSf-BP-6Ii"/>
<outlet property="tableView" destination="bgs-Kf-cQA" id="Nri-qd-wNS"/>

View file

@ -15,14 +15,19 @@ void CountryNameGetter::SetLocaleForTesting(string const & jsonBuffer, string co
m_getCurLang = platform::ForTestingGetTextByIdFactory(jsonBuffer, locale);
}
string CountryNameGetter::operator()(TCountryId const & countryId) const
string CountryNameGetter::Get(string const & key) const
{
ASSERT(!countryId.empty(), ());
ASSERT(!key.empty(), ());
if (m_getCurLang == nullptr)
return countryId;
return string();
string name = (*m_getCurLang)(countryId);
return (*m_getCurLang)(key);
}
string CountryNameGetter::operator()(TCountryId const & countryId) const
{
string const name = Get(countryId);
if (name.empty())
return countryId;

View file

@ -27,6 +27,11 @@ public:
/// \note See countries/languages.txt for the full list of available locales.
void SetLocale(string const & locale);
/// \brief Gets localized string for key. If not found returns empty string.
/// @param key is a string for lookup.
/// \note Unlike operator (), does not return key if localized string is not found.
string Get(string const & key) const;
string operator()(TCountryId const & countryId) const;
// for testing

View file

@ -1332,7 +1332,7 @@ void Storage::GetNodeAttrs(TCountryId const & countryId, NodeAttrs & nodeAttrs)
nodeAttrs.m_status = statusAndErr.status;
nodeAttrs.m_error = statusAndErr.error;
nodeAttrs.m_nodeLocalName = m_countryNameGetter(countryId);
nodeAttrs.m_nodeLocalDescription = m_countryNameGetter(countryId + LOCALIZATION_DESCRIPTION_SUFFIX);
nodeAttrs.m_nodeLocalDescription = m_countryNameGetter.Get(countryId + LOCALIZATION_DESCRIPTION_SUFFIX);
// Progress.
if (nodeAttrs.m_status == NodeStatus::OnDisk)