Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Yershov <syershov@maps.me>2016-12-16 10:10:39 +0300
committerGitHub <noreply@github.com>2016-12-16 10:10:39 +0300
commit04d05b53d200e35c125d0b80fbaa716a063cbea0 (patch)
treef43f1d5efdc4fc6e4fe73d1a1f7748afcefd89a6 /iphone/Maps/Settings
parentec9c0cd876b66d37b31116f3483ed7fc5241f62c (diff)
parent959974e43c1060d0717988bc67672af0247666bd (diff)
Merge pull request #5010 from igrechuhin/swift
[ios] Added Swift support.
Diffstat (limited to 'iphone/Maps/Settings')
-rw-r--r--iphone/Maps/Settings/Cells/SettingsTableViewLinkCell.swift27
-rw-r--r--iphone/Maps/Settings/Cells/SettingsTableViewSelectableCell.swift17
-rw-r--r--iphone/Maps/Settings/Cells/SettingsTableViewSwitchCell.swift43
-rw-r--r--iphone/Maps/Settings/LinkCell.h8
-rw-r--r--iphone/Maps/Settings/LinkCell.mm12
-rw-r--r--iphone/Maps/Settings/MWMAboutController.h5
-rw-r--r--iphone/Maps/Settings/MWMAboutController.mm136
-rw-r--r--iphone/Maps/Settings/MWMAboutControllerHeader.xib88
-rw-r--r--iphone/Maps/Settings/MWMHelpController.h5
-rw-r--r--iphone/Maps/Settings/MWMHelpController.mm254
-rw-r--r--iphone/Maps/Settings/MWMMobileInternetViewController.h5
-rw-r--r--iphone/Maps/Settings/MWMMobileInternetViewController.mm77
-rw-r--r--iphone/Maps/Settings/MWMNightModeController.h5
-rw-r--r--iphone/Maps/Settings/MWMNightModeController.mm102
-rw-r--r--iphone/Maps/Settings/MWMRecentTrackSettingsController.h5
-rw-r--r--iphone/Maps/Settings/MWMRecentTrackSettingsController.mm106
-rw-r--r--iphone/Maps/Settings/MWMSettings.h35
-rw-r--r--iphone/Maps/Settings/MWMSettings.mm153
-rw-r--r--iphone/Maps/Settings/MWMSettingsViewController.mm149
-rw-r--r--iphone/Maps/Settings/MWMTTSLanguageViewController.h5
-rw-r--r--iphone/Maps/Settings/MWMTTSLanguageViewController.mm45
-rw-r--r--iphone/Maps/Settings/MWMTTSSettingsViewController.h10
-rw-r--r--iphone/Maps/Settings/MWMTTSSettingsViewController.mm205
-rw-r--r--iphone/Maps/Settings/MWMUnitsController.h5
-rw-r--r--iphone/Maps/Settings/MWMUnitsController.mm57
-rw-r--r--iphone/Maps/Settings/SelectableCell.h7
-rw-r--r--iphone/Maps/Settings/SelectableCell.mm12
-rw-r--r--iphone/Maps/Settings/SwitchCell.h17
-rw-r--r--iphone/Maps/Settings/SwitchCell.mm18
29 files changed, 1469 insertions, 144 deletions
diff --git a/iphone/Maps/Settings/Cells/SettingsTableViewLinkCell.swift b/iphone/Maps/Settings/Cells/SettingsTableViewLinkCell.swift
new file mode 100644
index 0000000000..2ca6547bec
--- /dev/null
+++ b/iphone/Maps/Settings/Cells/SettingsTableViewLinkCell.swift
@@ -0,0 +1,27 @@
+@objc final class SettingsTableViewLinkCell: MWMTableViewCell {
+
+ @IBOutlet fileprivate weak var title: UILabel!
+ @IBOutlet fileprivate weak var info: UILabel!
+
+ func config(title: String, info: String?) {
+ backgroundColor = UIColor.white()
+
+ self.title.text = title
+ styleTitle()
+
+ self.info.text = info
+ self.info.isHidden = info == nil
+ styleInfo()
+ }
+
+ fileprivate func styleTitle() {
+ title.textColor = UIColor.blackPrimaryText()
+ title.font = UIFont.regular17()
+ }
+
+ fileprivate func styleInfo() {
+ info.textColor = UIColor.blackSecondaryText()
+ info.font = UIFont.regular17()
+ }
+
+}
diff --git a/iphone/Maps/Settings/Cells/SettingsTableViewSelectableCell.swift b/iphone/Maps/Settings/Cells/SettingsTableViewSelectableCell.swift
new file mode 100644
index 0000000000..d5df003c07
--- /dev/null
+++ b/iphone/Maps/Settings/Cells/SettingsTableViewSelectableCell.swift
@@ -0,0 +1,17 @@
+@objc final class SettingsTableViewSelectableCell: MWMTableViewCell {
+
+ @IBOutlet fileprivate weak var title: UILabel!
+
+ func config(title: String) {
+ backgroundColor = UIColor.white()
+
+ self.title.text = title
+ styleTitle()
+ }
+
+ fileprivate func styleTitle() {
+ title.textColor = UIColor.blackPrimaryText()
+ title.font = UIFont.regular17()
+ }
+
+}
diff --git a/iphone/Maps/Settings/Cells/SettingsTableViewSwitchCell.swift b/iphone/Maps/Settings/Cells/SettingsTableViewSwitchCell.swift
new file mode 100644
index 0000000000..0335f2d8d9
--- /dev/null
+++ b/iphone/Maps/Settings/Cells/SettingsTableViewSwitchCell.swift
@@ -0,0 +1,43 @@
+@objc protocol SettingsTableViewSwitchCellDelegate {
+
+ func switchCell(_ cell: SettingsTableViewSwitchCell, didChangeValue value: Bool)
+
+}
+
+@objc final class SettingsTableViewSwitchCell: MWMTableViewCell {
+
+ @IBOutlet fileprivate weak var title: UILabel!
+ @IBOutlet fileprivate weak var switchButton: UISwitch! {
+ didSet {
+ switchButton.addTarget(self, action: #selector(switchChanged), for: .valueChanged)
+ }
+ }
+
+ weak var delegate: SettingsTableViewSwitchCellDelegate?
+
+ func config(delegate: SettingsTableViewSwitchCellDelegate, title: String, isOn: Bool) {
+ backgroundColor = UIColor.white()
+
+ self.delegate = delegate
+
+ self.title.text = title
+ styleTitle()
+
+ self.switchButton.isOn = isOn
+ styleSwitchButton()
+ }
+
+ @IBAction fileprivate func switchChanged() {
+ delegate?.switchCell(self, didChangeValue: switchButton.isOn)
+ }
+
+ fileprivate func styleTitle() {
+ title.textColor = UIColor.blackPrimaryText()
+ title.font = UIFont.regular17()
+ }
+
+ fileprivate func styleSwitchButton() {
+ switchButton.onTintColor = UIColor.linkBlue()
+ }
+
+}
diff --git a/iphone/Maps/Settings/LinkCell.h b/iphone/Maps/Settings/LinkCell.h
deleted file mode 100644
index abbfce412d..0000000000
--- a/iphone/Maps/Settings/LinkCell.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#import "MWMTableViewCell.h"
-
-@interface LinkCell : MWMTableViewCell
-
-@property(nonatomic) IBOutlet UILabel * titleLabel;
-@property(nonatomic) IBOutlet UILabel * infoLabel;
-
-@end
diff --git a/iphone/Maps/Settings/LinkCell.mm b/iphone/Maps/Settings/LinkCell.mm
deleted file mode 100644
index 1ca486d125..0000000000
--- a/iphone/Maps/Settings/LinkCell.mm
+++ /dev/null
@@ -1,12 +0,0 @@
-#import "LinkCell.h"
-#import "UIColor+MapsMeColor.h"
-
-@implementation LinkCell
-
-- (void)awakeFromNib
-{
- [super awakeFromNib];
- self.backgroundColor = [UIColor white];
-}
-
-@end
diff --git a/iphone/Maps/Settings/MWMAboutController.h b/iphone/Maps/Settings/MWMAboutController.h
new file mode 100644
index 0000000000..bf44d902da
--- /dev/null
+++ b/iphone/Maps/Settings/MWMAboutController.h
@@ -0,0 +1,5 @@
+#import "MWMTableViewController.h"
+
+@interface MWMAboutController : MWMTableViewController
+
+@end
diff --git a/iphone/Maps/Settings/MWMAboutController.mm b/iphone/Maps/Settings/MWMAboutController.mm
new file mode 100644
index 0000000000..ba58e96647
--- /dev/null
+++ b/iphone/Maps/Settings/MWMAboutController.mm
@@ -0,0 +1,136 @@
+#import "MWMAboutController.h"
+#import "AppInfo.h"
+#import "MWMMailViewController.h"
+#import "Statistics.h"
+#import "SwiftBridge.h"
+#import "WebViewController.h"
+
+#import "3party/Alohalytics/src/alohalytics_objc.h"
+
+#include "Framework.h"
+
+#include "platform/platform.hpp"
+
+extern NSString * const kAlohalyticsTapEventKey;
+
+@interface MWMAboutController ()<MFMailComposeViewControllerDelegate>
+
+@property(weak, nonatomic) IBOutlet UILabel * versionLabel;
+@property(weak, nonatomic) IBOutlet UILabel * dateLabel;
+
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * websiteCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * blogCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * facebookCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * twitterCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * subscribeCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * rateCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * copyrightCell;
+
+@property(nonatomic) IBOutlet UIView * headerView;
+
+@end
+
+@implementation MWMAboutController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ self.title = L(@"about_menu_title");
+
+ [[NSBundle mainBundle] loadNibNamed:@"MWMAboutControllerHeader" owner:self options:nil];
+ self.tableView.tableHeaderView = self.headerView;
+
+ AppInfo * appInfo = [AppInfo sharedInfo];
+ NSString * version = appInfo.bundleVersion;
+ if (appInfo.buildNumber)
+ version = [NSString stringWithFormat:@"%@.%@", version, appInfo.buildNumber];
+ self.versionLabel.text = [NSString stringWithFormat:L(@"version"), version];
+
+ NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
+ dateFormatter.dateStyle = NSDateFormatterShortStyle;
+ dateFormatter.timeStyle = NSDateFormatterNoStyle;
+ auto const dataVersion = GetFramework().GetCurrentDataVersion();
+ self.dateLabel.text = [NSString stringWithFormat:L(@"date"), dataVersion];
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ [tableView deselectRowAtIndexPath:indexPath animated:YES];
+ auto cell = static_cast<SettingsTableViewLinkCell *>([tableView cellForRowAtIndexPath:indexPath]);
+ if (cell == self.websiteCell)
+ {
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"website"];
+ [self openUrl:[NSURL URLWithString:@"https://maps.me"]];
+ }
+ else if (cell == self.blogCell)
+ {
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"blog"];
+ [self openUrl:[NSURL URLWithString:@"http://blog.maps.me"]];
+ }
+ else if (cell == self.facebookCell)
+ {
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"likeOnFb"];
+ [self openUrl:[NSURL URLWithString:@"https://facebook.com/MapsWithMe"]];
+ }
+ else if (cell == self.twitterCell)
+ {
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"followOnTwitter"];
+ [self openUrl:[NSURL URLWithString:@"https://twitter.com/MAPS_ME"]];
+ }
+ else if (cell == self.subscribeCell)
+ {
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"subscribeToNews"];
+ [self sendEmailWithText:L(@"subscribe_me_body")
+ subject:L(@"subscribe_me_subject")
+ toRecipient:@"subscribe@maps.me"];
+ }
+ else if (cell == self.rateCell)
+ {
+ [Statistics logEvent:kStatSettingsOpenSection withParameters:@{kStatName : kStatRate}];
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"rate"];
+ [[UIApplication sharedApplication] rateVersionFrom:@"rate_menu_item"];
+ }
+ else if (cell == self.copyrightCell)
+ {
+ [Statistics logEvent:kStatSettingsOpenSection withParameters:@{kStatName : kStatCopyright}];
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"copyright"];
+ string s;
+ GetPlatform().GetReader("copyright.html")->ReadAsString(s);
+ NSString * text = [NSString stringWithFormat:@"%@\n%@", self.versionLabel.text, @(s.c_str())];
+ WebViewController * aboutViewController =
+ [[WebViewController alloc] initWithHtml:text baseUrl:nil andTitleOrNil:L(@"copyright")];
+ aboutViewController.openInSafari = YES;
+ [self.navigationController pushViewController:aboutViewController animated:YES];
+ }
+}
+
+- (void)sendEmailWithText:(NSString *)text subject:(NSString *)subject toRecipient:(NSString *)email
+{
+ if ([MWMMailViewController canSendMail])
+ {
+ MWMMailViewController * vc = [[MWMMailViewController alloc] init];
+ vc.mailComposeDelegate = self;
+ [vc setSubject:subject];
+ [vc setMessageBody:text isHTML:NO];
+ [vc setToRecipients:@[ email ]];
+ [self presentViewController:vc animated:YES completion:nil];
+ }
+ else
+ {
+ NSString * text = [NSString stringWithFormat:L(@"email_error_body"), email];
+ [[[UIAlertView alloc] initWithTitle:L(@"email_error_title")
+ message:text
+ delegate:nil
+ cancelButtonTitle:L(@"ok")
+ otherButtonTitles:nil] show];
+ }
+}
+
+- (void)mailComposeController:(MFMailComposeViewController *)controller
+ didFinishWithResult:(MFMailComposeResult)result
+ error:(NSError *)error
+{
+ [self dismissViewControllerAnimated:YES completion:nil];
+}
+
+@end
diff --git a/iphone/Maps/Settings/MWMAboutControllerHeader.xib b/iphone/Maps/Settings/MWMAboutControllerHeader.xib
new file mode 100644
index 0000000000..8adc47bd07
--- /dev/null
+++ b/iphone/Maps/Settings/MWMAboutControllerHeader.xib
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+ <device id="retina4_7" orientation="portrait">
+ <adaptation id="fullscreen"/>
+ </device>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
+ <capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <objects>
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MWMAboutController">
+ <connections>
+ <outlet property="dateLabel" destination="2UY-CN-bbR" id="0ad-Y1-yZq"/>
+ <outlet property="headerView" destination="nNn-As-qvg" id="kwi-x5-YnF"/>
+ <outlet property="versionLabel" destination="eX4-Y6-p2e" id="4Kf-ae-nY1"/>
+ </connections>
+ </placeholder>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+ <view contentMode="scaleToFill" id="nNn-As-qvg">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="276"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+ <subviews>
+ <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="imgLogo" translatesAutoresizingMaskIntoConstraints="NO" id="MNH-d1-GMj">
+ <rect key="frame" x="128" y="24" width="120" height="120"/>
+ <constraints>
+ <constraint firstAttribute="width" secondItem="MNH-d1-GMj" secondAttribute="height" multiplier="1:1" id="1UQ-pV-hI7"/>
+ <constraint firstAttribute="height" priority="750" constant="120" id="9ug-0X-yk5"/>
+ </constraints>
+ </imageView>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="Версия 6.3.0.318" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eX4-Y6-p2e">
+ <rect key="frame" x="119" y="156" width="137" height="21"/>
+ <fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <nil key="highlightedColor"/>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
+ <userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium17"/>
+ </userDefinedRuntimeAttributes>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="Дата 16.08.2016" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2UY-CN-bbR">
+ <rect key="frame" x="137" y="181" width="101" height="16"/>
+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <nil key="highlightedColor"/>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
+ <userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular13"/>
+ </userDefinedRuntimeAttributes>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="Объединив усилия Mail.Ru Group и данные OpenStreetMap, мы создаем незаменимое приложение для путешествий." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GEL-Bz-rHg">
+ <rect key="frame" x="8" y="205" width="359" height="47"/>
+ <fontDescription key="fontDescription" type="system" pointSize="13"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+ <nil key="highlightedColor"/>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
+ <userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular13"/>
+ <userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="about_description"/>
+ </userDefinedRuntimeAttributes>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ <constraints>
+ <constraint firstItem="MNH-d1-GMj" firstAttribute="top" secondItem="nNn-As-qvg" secondAttribute="top" constant="24" id="4Yk-N8-0X2"/>
+ <constraint firstItem="GEL-Bz-rHg" firstAttribute="centerX" secondItem="nNn-As-qvg" secondAttribute="centerX" id="6vn-WQ-qNy"/>
+ <constraint firstAttribute="trailing" secondItem="GEL-Bz-rHg" secondAttribute="trailing" constant="8" id="8IJ-ww-y0j"/>
+ <constraint firstItem="GEL-Bz-rHg" firstAttribute="top" secondItem="2UY-CN-bbR" secondAttribute="bottom" constant="8" id="AXP-EC-LMU"/>
+ <constraint firstItem="GEL-Bz-rHg" firstAttribute="leading" secondItem="nNn-As-qvg" secondAttribute="leading" constant="8" id="Fho-8h-fz5"/>
+ <constraint firstItem="MNH-d1-GMj" firstAttribute="centerX" secondItem="nNn-As-qvg" secondAttribute="centerX" id="ORf-Qo-mSu"/>
+ <constraint firstAttribute="bottom" secondItem="GEL-Bz-rHg" secondAttribute="bottom" constant="24" id="OgM-Is-GbO"/>
+ <constraint firstItem="2UY-CN-bbR" firstAttribute="top" secondItem="eX4-Y6-p2e" secondAttribute="bottom" constant="4" id="XUm-iH-rab"/>
+ <constraint firstItem="eX4-Y6-p2e" firstAttribute="centerX" secondItem="nNn-As-qvg" secondAttribute="centerX" id="jgK-Ga-gbr"/>
+ <constraint firstItem="eX4-Y6-p2e" firstAttribute="top" secondItem="MNH-d1-GMj" secondAttribute="bottom" constant="12" id="tbq-yy-OGh"/>
+ <constraint firstItem="2UY-CN-bbR" firstAttribute="centerX" secondItem="nNn-As-qvg" secondAttribute="centerX" id="zBm-aI-8kB"/>
+ </constraints>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="pressBackground"/>
+ </userDefinedRuntimeAttributes>
+ <point key="canvasLocation" x="131" y="-39"/>
+ </view>
+ </objects>
+ <resources>
+ <image name="imgLogo" width="120" height="120"/>
+ </resources>
+</document>
diff --git a/iphone/Maps/Settings/MWMHelpController.h b/iphone/Maps/Settings/MWMHelpController.h
new file mode 100644
index 0000000000..8906ecbabb
--- /dev/null
+++ b/iphone/Maps/Settings/MWMHelpController.h
@@ -0,0 +1,5 @@
+#import "MWMViewController.h"
+
+@interface MWMHelpController : MWMViewController
+
+@end
diff --git a/iphone/Maps/Settings/MWMHelpController.mm b/iphone/Maps/Settings/MWMHelpController.mm
new file mode 100644
index 0000000000..5ba66f4395
--- /dev/null
+++ b/iphone/Maps/Settings/MWMHelpController.mm
@@ -0,0 +1,254 @@
+#import "MWMHelpController.h"
+#import <sys/utsname.h>
+#import "AppInfo.h"
+#import "Common.h"
+#import "MWMMailViewController.h"
+#import "Statistics.h"
+#import "UIColor+MapsMeColor.h"
+#import "WebViewController.h"
+
+#import "3party/Alohalytics/src/alohalytics_objc.h"
+
+#include "platform/platform.hpp"
+
+extern NSString * const kAlohalyticsTapEventKey;
+extern NSString * const kLocaleUsedInSupportEmails = @"en_gb";
+extern NSDictionary * const kDeviceNames = @{
+ @"i386" : @"Simulator",
+ @"iPad1,1" : @"iPad WiFi",
+ @"iPad1,2" : @"iPad GSM",
+ @"iPad2,1" : @"iPad 2 WiFi",
+ @"iPad2,2" : @"iPad 2 CDMA",
+ @"iPad2,2" : @"iPad 2 GSM",
+ @"iPad2,3" : @"iPad 2 GSM EV-DO",
+ @"iPad2,4" : @"iPad 2",
+ @"iPad2,5" : @"iPad Mini WiFi",
+ @"iPad2,6" : @"iPad Mini GSM",
+ @"iPad2,7" : @"iPad Mini CDMA",
+ @"iPad3,1" : @"iPad 3rd gen. WiFi",
+ @"iPad3,2" : @"iPad 3rd gen. GSM",
+ @"iPad3,3" : @"iPad 3rd gen. CDMA",
+ @"iPad3,4" : @"iPad 4th gen. WiFi",
+ @"iPad3,5" : @"iPad 4th gen. GSM",
+ @"iPad3,6" : @"iPad 4th gen. CDMA",
+ @"iPad4,1" : @"iPad Air WiFi",
+ @"iPad4,2" : @"iPad Air GSM",
+ @"iPad4,3" : @"iPad Air CDMA",
+ @"iPad4,4" : @"iPad Mini 2nd gen. WiFi",
+ @"iPad4,5" : @"iPad Mini 2nd gen. GSM",
+ @"iPad4,6" : @"iPad Mini 2nd gen. CDMA",
+ @"iPad5,3" : @"iPad Air 2 WiFi",
+ @"iPad5,4" : @"iPad Air 2 GSM",
+ @"iPad6,3" : @"iPad Pro (9.7 inch) WiFi",
+ @"iPad6,4" : @"iPad Pro (9.7 inch) GSM",
+ @"iPad6,7" : @"iPad Pro (12.9 inch) WiFi",
+ @"iPad6,8" : @"iPad Pro (12.9 inch) GSM",
+ @"iPhone1,1" : @"iPhone",
+ @"iPhone1,2" : @"iPhone 3G",
+ @"iPhone2,1" : @"iPhone 3GS",
+ @"iPhone3,1" : @"iPhone 4 GSM",
+ @"iPhone3,2" : @"iPhone 4 CDMA",
+ @"iPhone3,3" : @"iPhone 4 GSM EV-DO",
+ @"iPhone4,1" : @"iPhone 4S",
+ @"iPhone4,2" : @"iPhone 4S",
+ @"iPhone4,3" : @"iPhone 4S",
+ @"iPhone5,1" : @"iPhone 5",
+ @"iPhone5,2" : @"iPhone 5",
+ @"iPhone5,3" : @"iPhone 5c",
+ @"iPhone5,4" : @"iPhone 5c",
+ @"iPhone6,1" : @"iPhone 5s",
+ @"iPhone6,2" : @"iPhone 5s",
+ @"iPhone7,1" : @"iPhone 6 Plus",
+ @"iPhone7,2" : @"iPhone 6",
+ @"iPhone8,1" : @"iPhone 6s",
+ @"iPhone8,2" : @"iPhone 6s Plus",
+ @"iPhone8,4" : @"iPhone SE",
+ @"iPod1,1" : @"iPod Touch",
+ @"iPod2,1" : @"iPod Touch 2nd gen.",
+ @"iPod3,1" : @"iPod Touch 3rd gen.",
+ @"iPod4,1" : @"iPod Touch 4th gen.",
+ @"iPod5,1" : @"iPod Touch 5th gen.",
+ @"x86_64" : @"Simulator",
+};
+
+namespace
+{
+NSString * const kCommonReportActionTitle = L(@"leave_a_review");
+NSString * const kBugReportActionTitle = L(@"something_is_not_working");
+NSString * const kCancelActionTitle = L(@"cancel");
+NSString * const kiOSEmail = @"ios@maps.me";
+}
+
+@interface MWMHelpController ()<MFMailComposeViewControllerDelegate>
+
+@property(nonatomic) WebViewController * aboutViewController;
+
+@property(weak, nonatomic) IBOutlet UIView * separatorView;
+
+@end // namespace
+
+@implementation MWMHelpController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ self.title = L(@"help");
+
+ NSString * html;
+ if (GetPlatform().ConnectionStatus() == Platform::EConnectionType::CONNECTION_NONE)
+ {
+ NSString * path = [[NSBundle mainBundle] pathForResource:@"faq" ofType:@"html"];
+ html = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
+ self.aboutViewController =
+ [[WebViewController alloc] initWithHtml:html baseUrl:nil andTitleOrNil:nil];
+ }
+ else
+ {
+ NSURL * url = [NSURL URLWithString:@"https://support.maps.me"];
+ self.aboutViewController = [[WebViewController alloc] initWithUrl:url andTitleOrNil:nil];
+ }
+
+ self.aboutViewController.openInSafari = NO;
+ UIView * aboutView = self.aboutViewController.view;
+ [self addChildViewController:self.aboutViewController];
+ [self.view addSubview:aboutView];
+
+ aboutView.translatesAutoresizingMaskIntoConstraints = NO;
+ NSLayoutConstraint * top = [NSLayoutConstraint constraintWithItem:self.view
+ attribute:NSLayoutAttributeTop
+ relatedBy:NSLayoutRelationEqual
+ toItem:aboutView
+ attribute:NSLayoutAttributeTop
+ multiplier:1.0
+ constant:0.0];
+ NSLayoutConstraint * bottom = [NSLayoutConstraint constraintWithItem:self.separatorView
+ attribute:NSLayoutAttributeTop
+ relatedBy:NSLayoutRelationEqual
+ toItem:aboutView
+ attribute:NSLayoutAttributeBottom
+ multiplier:1.0
+ constant:0.0];
+ NSLayoutConstraint * left = [NSLayoutConstraint constraintWithItem:self.view
+ attribute:NSLayoutAttributeLeft
+ relatedBy:NSLayoutRelationEqual
+ toItem:aboutView
+ attribute:NSLayoutAttributeLeft
+ multiplier:1.0
+ constant:0.0];
+ NSLayoutConstraint * right = [NSLayoutConstraint constraintWithItem:self.view
+ attribute:NSLayoutAttributeRight
+ relatedBy:NSLayoutRelationEqual
+ toItem:aboutView
+ attribute:NSLayoutAttributeRight
+ multiplier:1.0
+ constant:0.0];
+
+ [self.view addConstraints:@[ top, bottom, left, right ]];
+}
+
+- (IBAction)reportBug
+{
+ UIAlertController * alert =
+ [UIAlertController alertControllerWithTitle:L(@"feedback")
+ message:nil
+ preferredStyle:UIAlertControllerStyleAlert];
+
+ UIAlertAction * commonReport = [UIAlertAction actionWithTitle:kCommonReportActionTitle
+ style:UIAlertActionStyleDefault
+ handler:^(UIAlertAction * _Nonnull action) {
+ [self commonReportAction];
+ }];
+ [alert addAction:commonReport];
+
+ UIAlertAction * bugReport = [UIAlertAction actionWithTitle:kBugReportActionTitle
+ style:UIAlertActionStyleDefault
+ handler:^(UIAlertAction * _Nonnull action) {
+ [self bugReportAction];
+ }];
+ [alert addAction:bugReport];
+
+ UIAlertAction * cancel =
+ [UIAlertAction actionWithTitle:kCancelActionTitle style:UIAlertActionStyleCancel handler:nil];
+ [alert addAction:cancel];
+ alert.preferredAction = cancel;
+
+ [self presentViewController:alert animated:YES completion:nil];
+}
+
+#pragma mark - Actions
+
+- (void)commonReportAction
+{
+ [Statistics logEvent:kStatSettingsOpenSection withParameters:@{kStatName : kStatFeedback}];
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"contactUs"];
+ // Do not localize subject. Support team uses it to filter emails.
+ [self sendEmailWithSubject:@"Feedback from user" toRecipient:kiOSEmail];
+}
+
+- (void)bugReportAction
+{
+ [Statistics logEvent:kStatSettingsOpenSection withParameters:@{kStatName : kStatReport}];
+ [Alohalytics logEvent:kAlohalyticsTapEventKey withValue:@"reportABug"];
+ // Do not localize subject. Support team uses it to filter emails.
+ [self sendEmailWithSubject:@"Bug report from user" toRecipient:kiOSEmail];
+}
+
+#pragma mark - Email
+
+- (void)sendEmailWithSubject:(NSString *)subject toRecipient:(NSString *)email
+{
+ if ([MWMMailViewController canSendMail])
+ {
+ struct utsname systemInfo;
+ uname(&systemInfo);
+ NSString * machine =
+ [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
+ NSString * device = kDeviceNames[machine];
+ if (!device)
+ device = machine;
+ NSString * languageCode = [[NSLocale preferredLanguages] firstObject];
+ NSString * language = [[NSLocale localeWithLocaleIdentifier:kLocaleUsedInSupportEmails]
+ displayNameForKey:NSLocaleLanguageCode
+ value:languageCode];
+ NSString * locale = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
+ NSString * country = [[NSLocale localeWithLocaleIdentifier:kLocaleUsedInSupportEmails]
+ displayNameForKey:NSLocaleCountryCode
+ value:locale];
+ NSString * bundleVersion =
+ [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
+ NSString * text = [NSString stringWithFormat:@"\n\n\n\n- %@ (%@)\n- MAPS.ME %@\n- %@/%@",
+ device, [UIDevice currentDevice].systemVersion,
+ bundleVersion, language, country];
+ NSString * alohalyticsId = [Alohalytics installationId];
+ if (alohalyticsId)
+ text = [NSString stringWithFormat:@"%@\n- %@", text, alohalyticsId];
+
+ MWMMailViewController * vc = [[MWMMailViewController alloc] init];
+ vc.mailComposeDelegate = self;
+ [vc setSubject:[NSString stringWithFormat:@"[%@ iOS] %@", [AppInfo sharedInfo].bundleVersion,
+ subject]];
+ [vc setMessageBody:text isHTML:NO];
+ [vc setToRecipients:@[ email ]];
+ [vc.navigationBar setTintColor:[UIColor whitePrimaryText]];
+ [self presentViewController:vc animated:YES completion:nil];
+ }
+ else
+ {
+ NSString * text = [NSString stringWithFormat:L(@"email_error_body"), email];
+ [[[UIAlertView alloc] initWithTitle:L(@"email_error_title")
+ message:text
+ delegate:nil
+ cancelButtonTitle:L(@"ok")
+ otherButtonTitles:nil] show];
+ }
+}
+
+- (void)mailComposeController:(MFMailComposeViewController *)controller
+ didFinishWithResult:(MFMailComposeResult)result
+ error:(NSError *)error
+{
+ [self dismissViewControllerAnimated:YES completion:nil];
+}
+
+@end
diff --git a/iphone/Maps/Settings/MWMMobileInternetViewController.h b/iphone/Maps/Settings/MWMMobileInternetViewController.h
new file mode 100644
index 0000000000..bdd9ce1e5b
--- /dev/null
+++ b/iphone/Maps/Settings/MWMMobileInternetViewController.h
@@ -0,0 +1,5 @@
+#import "MWMTableViewController.h"
+
+@interface MWMMobileInternetViewController : MWMTableViewController
+
+@end
diff --git a/iphone/Maps/Settings/MWMMobileInternetViewController.mm b/iphone/Maps/Settings/MWMMobileInternetViewController.mm
new file mode 100644
index 0000000000..a2bca313fd
--- /dev/null
+++ b/iphone/Maps/Settings/MWMMobileInternetViewController.mm
@@ -0,0 +1,77 @@
+#import "MWMMobileInternetViewController.h"
+#import "MWMNetworkPolicy.h"
+#import "Statistics.h"
+#import "SwiftBridge.h"
+
+using namespace network_policy;
+using np = platform::NetworkPolicy;
+
+@interface MWMMobileInternetViewController ()
+
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * always;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * ask;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * never;
+@property(weak, nonatomic) SettingsTableViewSelectableCell * selected;
+
+@end
+
+@implementation MWMMobileInternetViewController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ self.title = L(@"mobile_data");
+
+ SettingsTableViewSelectableCell * selected;
+ switch (GetStage())
+ {
+ case np::Stage::Always: selected = self.always; break;
+ case np::Stage::Session: selected = self.ask; break;
+ case np::Stage::Never: selected = self.never; break;
+ }
+ selected.accessoryType = UITableViewCellAccessoryCheckmark;
+ self.selected = selected;
+}
+
+- (void)setSelected:(SettingsTableViewSelectableCell *)selected
+{
+ if ([_selected isEqual:selected])
+ return;
+
+ _selected = selected;
+ NSString * statValue = nil;
+ if ([selected isEqual:self.always])
+ {
+ statValue = kStatAlways;
+ SetStage(np::Stage::Always);
+ }
+ else if ([selected isEqual:self.ask])
+ {
+ statValue = kStatAsk;
+ SetStage(np::Stage::Session);
+ }
+ else if ([selected isEqual:self.never])
+ {
+ statValue = kStatNever;
+ SetStage(np::Stage::Never);
+ }
+
+ [Statistics logEvent:kStatMobileInternet withParameters:@{kStatValue : statValue}];
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ SettingsTableViewSelectableCell * selected = self.selected;
+ selected.accessoryType = UITableViewCellAccessoryNone;
+ selected = [tableView cellForRowAtIndexPath:indexPath];
+ selected.accessoryType = UITableViewCellAccessoryCheckmark;
+ selected.selected = NO;
+ self.selected = selected;
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
+{
+ return L(@"mobile_data_description");
+}
+
+@end
diff --git a/iphone/Maps/Settings/MWMNightModeController.h b/iphone/Maps/Settings/MWMNightModeController.h
new file mode 100644
index 0000000000..27b77f6f56
--- /dev/null
+++ b/iphone/Maps/Settings/MWMNightModeController.h
@@ -0,0 +1,5 @@
+#import "MWMTableViewController.h"
+
+@interface MWMNightModeController : MWMTableViewController
+
+@end
diff --git a/iphone/Maps/Settings/MWMNightModeController.mm b/iphone/Maps/Settings/MWMNightModeController.mm
new file mode 100644
index 0000000000..96e209e88d
--- /dev/null
+++ b/iphone/Maps/Settings/MWMNightModeController.mm
@@ -0,0 +1,102 @@
+#import "MWMNightModeController.h"
+#import "MWMSettings.h"
+#import "MapsAppDelegate.h"
+#import "Statistics.h"
+#import "SwiftBridge.h"
+#import "UIColor+MapsMeColor.h"
+
+#include "Framework.h"
+
+@interface MWMNightModeController ()
+
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * autoSwitch;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * on;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * off;
+@property(weak, nonatomic) SettingsTableViewSelectableCell * selectedCell;
+
+@end
+
+@implementation MWMNightModeController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ self.title = L(@"pref_map_style_title");
+ if ([MWMSettings autoNightModeEnabled])
+ {
+ self.autoSwitch.accessoryType = UITableViewCellAccessoryCheckmark;
+ _selectedCell = self.autoSwitch;
+ return;
+ }
+
+ switch (GetFramework().GetMapStyle())
+ {
+ case MapStyleDark:
+ self.on.accessoryType = UITableViewCellAccessoryCheckmark;
+ _selectedCell = self.on;
+ break;
+ case MapStyleClear:
+ case MapStyleLight:
+ self.off.accessoryType = UITableViewCellAccessoryCheckmark;
+ _selectedCell = self.off;
+ break;
+ case MapStyleMerged:
+ case MapStyleCount: break;
+ }
+}
+
+- (void)setSelectedCell:(SettingsTableViewSelectableCell *)cell
+{
+ if ([_selectedCell isEqual:cell])
+ return;
+
+ _selectedCell = cell;
+ auto & f = GetFramework();
+ auto const style = f.GetMapStyle();
+ NSString * statValue = nil;
+ if ([cell isEqual:self.on])
+ {
+ [MapsAppDelegate setAutoNightModeOff:YES];
+ if (style == MapStyleDark)
+ return;
+ f.SetMapStyle(MapStyleDark);
+ [UIColor setNightMode:YES];
+ [self mwm_refreshUI];
+ statValue = kStatOn;
+ }
+ else if ([cell isEqual:self.off])
+ {
+ [MapsAppDelegate setAutoNightModeOff:YES];
+ if (style == MapStyleClear || style == MapStyleLight)
+ return;
+ f.SetMapStyle(MapStyleClear);
+ [UIColor setNightMode:NO];
+ [self mwm_refreshUI];
+ statValue = kStatOff;
+ }
+ else if ([cell isEqual:self.autoSwitch])
+ {
+ [MapsAppDelegate setAutoNightModeOff:NO];
+ [MapsAppDelegate changeMapStyleIfNedeed];
+ if (style == MapStyleClear || style == MapStyleLight)
+ return;
+ [UIColor setNightMode:NO];
+ f.SetMapStyle(MapStyleClear);
+ [self mwm_refreshUI];
+ statValue = kStatValue;
+ }
+
+ [Statistics logEvent:kStatNightMode withParameters:@{kStatValue : statValue}];
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ SettingsTableViewSelectableCell * selectedCell = self.selectedCell;
+ selectedCell.accessoryType = UITableViewCellAccessoryNone;
+ selectedCell = [tableView cellForRowAtIndexPath:indexPath];
+ selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
+ selectedCell.selected = NO;
+ self.selectedCell = selectedCell;
+}
+
+@end
diff --git a/iphone/Maps/Settings/MWMRecentTrackSettingsController.h b/iphone/Maps/Settings/MWMRecentTrackSettingsController.h
new file mode 100644
index 0000000000..4266571020
--- /dev/null
+++ b/iphone/Maps/Settings/MWMRecentTrackSettingsController.h
@@ -0,0 +1,5 @@
+#import "MWMTableViewController.h"
+
+@interface MWMRecentTrackSettingsController : MWMTableViewController
+
+@end
diff --git a/iphone/Maps/Settings/MWMRecentTrackSettingsController.mm b/iphone/Maps/Settings/MWMRecentTrackSettingsController.mm
new file mode 100644
index 0000000000..5e3b726ec9
--- /dev/null
+++ b/iphone/Maps/Settings/MWMRecentTrackSettingsController.mm
@@ -0,0 +1,106 @@
+#import "MWMRecentTrackSettingsController.h"
+#import "Statistics.h"
+#import "SwiftBridge.h"
+
+#include "Framework.h"
+
+#include "map/gps_tracker.hpp"
+
+extern NSString * const kUDTrackWarningAlertWasShown = @"TrackWarningAlertWasShown";
+
+typedef NS_ENUM(NSUInteger, DurationInHours) { One = 1, Two = 2, Six = 6, Twelve = 12, Day = 24 };
+
+@interface MWMRecentTrackSettingsController ()
+
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * none;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * oneHour;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * twoHours;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * sixHours;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * twelveHours;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * oneDay;
+@property(weak, nonatomic) SettingsTableViewSelectableCell * selectedCell;
+
+@end
+
+@implementation MWMRecentTrackSettingsController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ self.title = L(@"pref_track_record_title");
+
+ if (!GpsTracker::Instance().IsEnabled())
+ {
+ _selectedCell = self.none;
+ }
+ else
+ {
+ switch (GpsTracker::Instance().GetDuration().count())
+ {
+ case One: _selectedCell = self.oneHour; break;
+ case Two: _selectedCell = self.twoHours; break;
+ case Six: _selectedCell = self.sixHours; break;
+ case Twelve: _selectedCell = self.twelveHours; break;
+ case Day: _selectedCell = self.oneDay; break;
+ default: NSAssert(false, @"Incorrect hours value"); break;
+ }
+ }
+ self.selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
+}
+
+- (void)setSelectedCell:(SettingsTableViewSelectableCell *)selectedCell
+{
+ _selectedCell = selectedCell;
+ auto & f = GetFramework();
+ auto & tracker = GpsTracker::Instance();
+ NSString * statValue = nil;
+ if ([selectedCell isEqual:self.none])
+ {
+ f.DisconnectFromGpsTracker();
+ tracker.SetEnabled(false);
+ statValue = kStatOff;
+ }
+ else
+ {
+ if (!tracker.IsEnabled())
+ {
+ tracker.SetEnabled(true);
+ NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
+ [ud setBool:NO forKey:kUDTrackWarningAlertWasShown];
+ [ud synchronize];
+ }
+ f.ConnectToGpsTracker();
+
+ if ([selectedCell isEqual:self.oneHour])
+ tracker.SetDuration(hours(One));
+ else if ([selectedCell isEqual:self.twoHours])
+ tracker.SetDuration(hours(Two));
+ else if ([selectedCell isEqual:self.sixHours])
+ tracker.SetDuration(hours(Six));
+ else if ([selectedCell isEqual:self.twelveHours])
+ tracker.SetDuration(hours(Twelve));
+ else
+ tracker.SetDuration(hours(Day));
+
+ statValue = [NSString stringWithFormat:@"%@ hour(s)", @(tracker.GetDuration().count())];
+ }
+ selectedCell.accessoryType = UITableViewCellAccessoryCheckmark;
+ [Statistics logEvent:kStatChangeRecentTrack withParameters:@{kStatValue : statValue}];
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ SettingsTableViewSelectableCell * selectedCell = self.selectedCell;
+ selectedCell.accessoryType = UITableViewCellAccessoryNone;
+ selectedCell = [tableView cellForRowAtIndexPath:indexPath];
+ selectedCell.selected = NO;
+ self.selectedCell = selectedCell;
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
+{
+ NSAssert(section == 0, @"Incorrect sections count");
+ return L(@"recent_track_help_text");
+}
+
+@end
diff --git a/iphone/Maps/Settings/MWMSettings.h b/iphone/Maps/Settings/MWMSettings.h
new file mode 100644
index 0000000000..f2d612c6db
--- /dev/null
+++ b/iphone/Maps/Settings/MWMSettings.h
@@ -0,0 +1,35 @@
+#include "platform/measurement_utils.hpp"
+
+@interface MWMSettings : NSObject
+
++ (BOOL)adServerForbidden;
++ (void)setAdServerForbidden:(BOOL)adServerForbidden;
+
++ (BOOL)adForbidden;
++ (void)setAdForbidden:(BOOL)adForbidden;
+
++ (BOOL)autoDownloadEnabled;
++ (void)setAutoDownloadEnabled:(BOOL)autoDownloadEnabled;
+
++ (measurement_utils::Units)measurementUnits;
++ (void)setMeasurementUnits:(measurement_utils::Units)measurementUnits;
+
++ (BOOL)zoomButtonsEnabled;
++ (void)setZoomButtonsEnabled:(BOOL)zoomButtonsEnabled;
+
++ (BOOL)compassCalibrationEnabled;
++ (void)setCompassCalibrationEnabled:(BOOL)compassCalibrationEnabled;
+
++ (BOOL)statisticsEnabled;
++ (void)setStatisticsEnabled:(BOOL)statisticsEnabled;
+
++ (BOOL)autoNightModeEnabled;
++ (void)setAutoNightModeEnabled:(BOOL)autoNightModeEnabled;
+
++ (BOOL)routingDisclaimerApproved;
++ (void)setRoutingDisclaimerApproved;
+
++ (NSString *)spotlightLocaleLanguageId;
++ (void)setSpotlightLocaleLanguageId:(NSString *)spotlightLocaleLanguageId;
+
+@end
diff --git a/iphone/Maps/Settings/MWMSettings.mm b/iphone/Maps/Settings/MWMSettings.mm
new file mode 100644
index 0000000000..bcb055a62b
--- /dev/null
+++ b/iphone/Maps/Settings/MWMSettings.mm
@@ -0,0 +1,153 @@
+#import "MWMSettings.h"
+#import "MWMMapViewControlsManager.h"
+
+#import "3party/Alohalytics/src/alohalytics_objc.h"
+
+#include "Framework.h"
+
+#include "platform/settings.hpp"
+
+namespace
+{
+char const * kAdForbiddenSettingsKey = "AdForbidden";
+char const * kAdServerForbiddenKey = "AdServerForbidden";
+char const * kAutoDownloadEnabledKey = "AutoDownloadEnabled";
+char const * kZoomButtonsEnabledKey = "ZoomButtonsEnabled";
+char const * kCompassCalibrationEnabledKey = "CompassCalibrationEnabled";
+char const * kRoutingDisclaimerApprovedKey = "IsDisclaimerApproved";
+char const * kStatisticsEnabledSettingsKey = "StatisticsEnabled";
+
+NSString * const kUDAutoNightModeOff = @"AutoNightModeOff";
+NSString * const kSpotlightLocaleLanguageId = @"SpotlightLocaleLanguageId";
+} // namespace
+
+@implementation MWMSettings
+
++ (BOOL)adServerForbidden
+{
+ bool adServerForbidden = false;
+ UNUSED_VALUE(settings::Get(kAdServerForbiddenKey, adServerForbidden));
+ return adServerForbidden;
+}
+
++ (void)setAdServerForbidden:(BOOL)adServerForbidden
+{
+ settings::Set(kAdServerForbiddenKey, static_cast<bool>(adServerForbidden));
+}
+
++ (BOOL)adForbidden
+{
+ bool adForbidden = false;
+ UNUSED_VALUE(settings::Get(kAdForbiddenSettingsKey, adForbidden));
+ return adForbidden;
+}
+
++ (void)setAdForbidden:(BOOL)adForbidden
+{
+ settings::Set(kAdForbiddenSettingsKey, static_cast<bool>(adForbidden));
+}
+
++ (BOOL)autoDownloadEnabled
+{
+ bool autoDownloadEnabled = true;
+ UNUSED_VALUE(settings::Get(kAutoDownloadEnabledKey, autoDownloadEnabled));
+ return autoDownloadEnabled;
+}
+
++ (void)setAutoDownloadEnabled:(BOOL)autoDownloadEnabled
+{
+ settings::Set(kAutoDownloadEnabledKey, static_cast<bool>(autoDownloadEnabled));
+}
+
++ (measurement_utils::Units)measurementUnits
+{
+ auto units = measurement_utils::Units::Metric;
+ UNUSED_VALUE(settings::Get(settings::kMeasurementUnits, units));
+ return units;
+}
+
++ (void)setMeasurementUnits:(measurement_utils::Units)measurementUnits
+{
+ settings::Set(settings::kMeasurementUnits, measurementUnits);
+ GetFramework().SetupMeasurementSystem();
+}
+
++ (BOOL)zoomButtonsEnabled
+{
+ bool enabled = true;
+ UNUSED_VALUE(settings::Get(kZoomButtonsEnabledKey, enabled));
+ return enabled;
+}
+
++ (void)setZoomButtonsEnabled:(BOOL)zoomButtonsEnabled
+{
+ settings::Set(kZoomButtonsEnabledKey, static_cast<bool>(zoomButtonsEnabled));
+ [MWMMapViewControlsManager manager].zoomHidden = !zoomButtonsEnabled;
+}
+
++ (BOOL)compassCalibrationEnabled
+{
+ bool enabled = true;
+ UNUSED_VALUE(settings::Get(kCompassCalibrationEnabledKey, enabled));
+ return enabled;
+}
+
++ (void)setCompassCalibrationEnabled:(BOOL)compassCalibrationEnabled
+{
+ settings::Set(kCompassCalibrationEnabledKey, static_cast<bool>(compassCalibrationEnabled));
+}
+
++ (BOOL)statisticsEnabled
+{
+ bool enabled = true;
+ UNUSED_VALUE(settings::Get(kStatisticsEnabledSettingsKey, enabled));
+ return enabled;
+}
+
++ (void)setStatisticsEnabled:(BOOL)statisticsEnabled
+{
+ if (statisticsEnabled)
+ {
+ [Alohalytics enable];
+ }
+ else
+ {
+ [Alohalytics logEvent:@"statisticsDisabled"];
+ [Alohalytics disable];
+ }
+ settings::Set(kStatisticsEnabledSettingsKey, static_cast<bool>(statisticsEnabled));
+}
+
++ (BOOL)autoNightModeEnabled
+{
+ return ![[NSUserDefaults standardUserDefaults] boolForKey:kUDAutoNightModeOff];
+}
+
++ (void)setAutoNightModeEnabled:(BOOL)autoNightModeEnabled
+{
+ NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
+ [ud setBool:!autoNightModeEnabled forKey:kUDAutoNightModeOff];
+ [ud synchronize];
+}
+
++ (BOOL)routingDisclaimerApproved
+{
+ bool enabled = false;
+ UNUSED_VALUE(settings::Get(kRoutingDisclaimerApprovedKey, enabled));
+ return enabled;
+}
+
++ (void)setRoutingDisclaimerApproved { settings::Set(kRoutingDisclaimerApprovedKey, true); }
++ (NSString *)spotlightLocaleLanguageId
+{
+ return [[NSUserDefaults standardUserDefaults] stringForKey:kSpotlightLocaleLanguageId];
+}
+
++ (void)setSpotlightLocaleLanguageId:(NSString *)spotlightLocaleLanguageId
+{
+ NSUserDefaults * ud = [NSUserDefaults standardUserDefaults];
+ [ud setObject:spotlightLocaleLanguageId forKey:kSpotlightLocaleLanguageId];
+ [ud synchronize];
+}
+
+@end
diff --git a/iphone/Maps/Settings/MWMSettingsViewController.mm b/iphone/Maps/Settings/MWMSettingsViewController.mm
index 881db9ec5d..873141db22 100644
--- a/iphone/Maps/Settings/MWMSettingsViewController.mm
+++ b/iphone/Maps/Settings/MWMSettingsViewController.mm
@@ -1,12 +1,11 @@
#import "MWMSettingsViewController.h"
-#import "LinkCell.h"
#import "LocaleTranslator.h"
#import "MWMAuthorizationCommon.h"
#import "MWMNetworkPolicy.h"
#import "MWMSettings.h"
#import "MWMTextToSpeech.h"
#import "Statistics.h"
-#import "SwitchCell.h"
+#import "SwiftBridge.h"
#import "WebViewController.h"
#import "3party/Alohalytics/src/alohalytics_objc.h"
@@ -17,27 +16,27 @@
extern NSString * const kAlohalyticsTapEventKey;
-@interface MWMSettingsViewController ()<SwitchCellDelegate>
+@interface MWMSettingsViewController ()<SettingsTableViewSwitchCellDelegate>
-@property(weak, nonatomic) IBOutlet LinkCell * profileCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * profileCell;
-@property(weak, nonatomic) IBOutlet LinkCell * unitsCell;
-@property(weak, nonatomic) IBOutlet SwitchCell * zoomButtonsCell;
-@property(weak, nonatomic) IBOutlet SwitchCell * is3dCell;
-@property(weak, nonatomic) IBOutlet SwitchCell * autoDownloadCell;
-@property(weak, nonatomic) IBOutlet LinkCell * mobileInternetCell;
-@property(weak, nonatomic) IBOutlet LinkCell * recentTrackCell;
-@property(weak, nonatomic) IBOutlet SwitchCell * compassCalibrationCell;
-@property(weak, nonatomic) IBOutlet SwitchCell * showOffersCell;
-@property(weak, nonatomic) IBOutlet SwitchCell * statisticsCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * unitsCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSwitchCell * zoomButtonsCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSwitchCell * is3dCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSwitchCell * autoDownloadCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * mobileInternetCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * recentTrackCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSwitchCell * compassCalibrationCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSwitchCell * showOffersCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSwitchCell * statisticsCell;
-@property(weak, nonatomic) IBOutlet LinkCell * nightModeCell;
-@property(weak, nonatomic) IBOutlet SwitchCell * perspectiveViewCell;
-@property(weak, nonatomic) IBOutlet SwitchCell * autoZoomCell;
-@property(weak, nonatomic) IBOutlet LinkCell * voiceInstructionsCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * nightModeCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSwitchCell * perspectiveViewCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSwitchCell * autoZoomCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * voiceInstructionsCell;
-@property(weak, nonatomic) IBOutlet LinkCell * helpCell;
-@property(weak, nonatomic) IBOutlet LinkCell * aboutCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * helpCell;
+@property(weak, nonatomic) IBOutlet SettingsTableViewLinkCell * aboutCell;
@end
@@ -60,116 +59,126 @@ extern NSString * const kAlohalyticsTapEventKey;
[self configProfileSection];
[self configCommonSection];
[self configNavigationSection];
+ [self configInfoSection];
}
- (void)configProfileSection
{
NSString * userName = osm_auth_ios::OSMUserName();
- self.profileCell.infoLabel.text = userName.length != 0 ? userName : @"";
+ [self.profileCell configWithTitle:L(@"profile") info:userName.length != 0 ? userName : @""];
}
- (void)configCommonSection
{
+ NSString * units = nil;
switch ([MWMSettings measurementUnits])
{
- case measurement_utils::Units::Metric: self.unitsCell.infoLabel.text = L(@"kilometres"); break;
- case measurement_utils::Units::Imperial: self.unitsCell.infoLabel.text = L(@"miles"); break;
+ case measurement_utils::Units::Metric: units = L(@"kilometres"); break;
+ case measurement_utils::Units::Imperial: units = L(@"miles"); break;
}
+ [self.unitsCell configWithTitle:L(@"measurement_units") info:units];
- self.zoomButtonsCell.switchButton.on = [MWMSettings zoomButtonsEnabled];
- self.zoomButtonsCell.delegate = self;
+ [self.zoomButtonsCell configWithDelegate:self
+ title:L(@"pref_zoom_title")
+ isOn:[MWMSettings zoomButtonsEnabled]];
bool on = true, _ = true;
GetFramework().Load3dMode(_, on);
- self.is3dCell.switchButton.on = on;
- self.is3dCell.delegate = self;
+ [self.is3dCell configWithDelegate:self title:L(@"pref_map_3d_buildings_title") isOn:on];
- self.autoDownloadCell.switchButton.on = [MWMSettings autoDownloadEnabled];
- self.autoDownloadCell.delegate = self;
+ [self.autoDownloadCell configWithDelegate:self
+ title:L(@"autodownload")
+ isOn:[MWMSettings autoDownloadEnabled]];
- NSString * internetLabel = nil;
- using np = platform::NetworkPolicy;
+ NSString * mobileInternet = nil;
+ using stage = platform::NetworkPolicy::Stage;
switch (network_policy::GetStage())
{
- case np::Stage::Always: internetLabel = L(@"mobile_data_option_always"); break;
- case np::Stage::Session: internetLabel = L(@"mobile_data_option_today"); break;
- case np::Stage::Never: internetLabel = L(@"mobile_data_option_never"); break;
+ case stage::Always: mobileInternet = L(@"mobile_data_option_always"); break;
+ case stage::Session: mobileInternet = L(@"mobile_data_option_today"); break;
+ case stage::Never: mobileInternet = L(@"mobile_data_option_never"); break;
}
- self.mobileInternetCell.infoLabel.text = internetLabel;
+ [self.mobileInternetCell configWithTitle:L(@"mobile_data") info:mobileInternet];
+
+ NSString * recentTrack = nil;
if (!GpsTracker::Instance().IsEnabled())
{
- self.recentTrackCell.infoLabel.text = L(@"duration_disabled");
+ recentTrack = L(@"duration_disabled");
}
else
{
switch (GpsTracker::Instance().GetDuration().count())
{
- case 1: self.recentTrackCell.infoLabel.text = L(@"duration_1_hour"); break;
- case 2: self.recentTrackCell.infoLabel.text = L(@"duration_2_hours"); break;
- case 6: self.recentTrackCell.infoLabel.text = L(@"duration_6_hours"); break;
- case 12: self.recentTrackCell.infoLabel.text = L(@"duration_12_hours"); break;
- case 24: self.recentTrackCell.infoLabel.text = L(@"duration_1_day"); break;
+ case 1: recentTrack = L(@"duration_1_hour"); break;
+ case 2: recentTrack = L(@"duration_2_hours"); break;
+ case 6: recentTrack = L(@"duration_6_hours"); break;
+ case 12: recentTrack = L(@"duration_12_hours"); break;
+ case 24: recentTrack = L(@"duration_1_day"); break;
default: NSAssert(false, @"Incorrect hours value"); break;
}
}
+ [self.recentTrackCell configWithTitle:L(@"pref_track_record_title") info:recentTrack];
+
- self.compassCalibrationCell.switchButton.on = [MWMSettings compassCalibrationEnabled];
- self.compassCalibrationCell.delegate = self;
+ [self.compassCalibrationCell configWithDelegate:self
+ title:L(@"pref_calibration_title")
+ isOn:[MWMSettings compassCalibrationEnabled]];
- self.showOffersCell.switchButton.on = ![MWMSettings adForbidden];
- self.showOffersCell.delegate = self;
+ [self.showOffersCell configWithDelegate:self
+ title:L(@"showcase_settings_title")
+ isOn:![MWMSettings adForbidden]];
- self.statisticsCell.switchButton.on = [MWMSettings statisticsEnabled];
- self.statisticsCell.delegate = self;
+ [self.statisticsCell configWithDelegate:self
+ title:L(@"allow_statistics")
+ isOn:[MWMSettings statisticsEnabled]];
}
- (void)configNavigationSection
{
+ NSString * nightMode = nil;
if ([MWMSettings autoNightModeEnabled])
- {
- self.nightModeCell.infoLabel.text = L(@"pref_map_style_auto");
- }
+ nightMode = L(@"pref_map_style_auto");
+ else if (GetFramework().GetMapStyle() == MapStyleDark)
+ nightMode = L(@"pref_map_style_night");
else
- {
- switch (GetFramework().GetMapStyle())
- {
- case MapStyleDark: self.nightModeCell.infoLabel.text = L(@"pref_map_style_night"); break;
- default: self.nightModeCell.infoLabel.text = L(@"pref_map_style_default"); break;
- }
- }
+ nightMode = L(@"pref_map_style_default");
+ [self.nightModeCell configWithTitle:L(@"pref_map_style_title") info:nightMode];
bool _ = true, on = true;
GetFramework().Load3dMode(on, _);
- self.perspectiveViewCell.switchButton.on = on;
- self.perspectiveViewCell.delegate = self;
+ [self.perspectiveViewCell configWithDelegate:self title:L(@"pref_map_3d_title") isOn:on];
- self.autoZoomCell.switchButton.on = GetFramework().LoadAutoZoom();
- self.autoZoomCell.delegate = self;
+ [self.autoZoomCell configWithDelegate:self
+ title:L(@"pref_map_auto_zoom")
+ isOn:GetFramework().LoadAutoZoom()];
+ NSString * voiceInstructions = nil;
if ([MWMTextToSpeech isTTSEnabled])
{
NSString * savedLanguage = [MWMTextToSpeech savedLanguage];
if (savedLanguage.length != 0)
{
string const savedLanguageTwine = locale_translator::bcp47ToTwineLanguage(savedLanguage);
- NSString * language = @(tts::translatedTwine(savedLanguageTwine).c_str());
- self.voiceInstructionsCell.infoLabel.text = language;
- }
- else
- {
- self.voiceInstructionsCell.infoLabel.text = @"";
+ voiceInstructions = @(tts::translatedTwine(savedLanguageTwine).c_str());
}
}
else
{
- self.voiceInstructionsCell.infoLabel.text = L(@"duration_disabled");
+ voiceInstructions = L(@"duration_disabled");
}
+ [self.voiceInstructionsCell configWithTitle:L(@"pref_tts_language_title") info:voiceInstructions];
+}
+
+- (void)configInfoSection
+{
+ [self.helpCell configWithTitle:L(@"help") info:nil];
+ [self.aboutCell configWithTitle:L(@"about_menu_title") info:nil];
}
-#pragma mark - SwitchCellDelegate
+#pragma mark - SettingsTableViewSwitchCellDelegate
-- (void)switchCell:(SwitchCell *)cell didChangeValue:(BOOL)value
+- (void)switchCell:(SettingsTableViewSwitchCell *)cell didChangeValue:(BOOL)value
{
if (cell == self.zoomButtonsCell)
{
@@ -240,7 +249,7 @@ extern NSString * const kAlohalyticsTapEventKey;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
- LinkCell * cell = static_cast<LinkCell *>([tableView cellForRowAtIndexPath:indexPath]);
+ auto cell = static_cast<SettingsTableViewLinkCell *>([tableView cellForRowAtIndexPath:indexPath]);
if (cell == self.profileCell)
{
[Statistics logEvent:kStatSettingsOpenSection withParameters:@{kStatName : kStatAuthorization}];
diff --git a/iphone/Maps/Settings/MWMTTSLanguageViewController.h b/iphone/Maps/Settings/MWMTTSLanguageViewController.h
new file mode 100644
index 0000000000..a7b6a64ac2
--- /dev/null
+++ b/iphone/Maps/Settings/MWMTTSLanguageViewController.h
@@ -0,0 +1,5 @@
+#import "MWMTableViewController.h"
+
+@interface MWMTTSLanguageViewController : MWMTableViewController
+
+@end
diff --git a/iphone/Maps/Settings/MWMTTSLanguageViewController.mm b/iphone/Maps/Settings/MWMTTSLanguageViewController.mm
new file mode 100644
index 0000000000..4529c4214f
--- /dev/null
+++ b/iphone/Maps/Settings/MWMTTSLanguageViewController.mm
@@ -0,0 +1,45 @@
+#import "MWMTTSLanguageViewController.h"
+#import "MWMTTSSettingsViewController.h"
+#import "MWMTextToSpeech.h"
+#import "SwiftBridge.h"
+#import "UIColor+MapsMeColor.h"
+
+static NSString * const kUnwingSegueIdentifier = @"UnwindToTTSSettings";
+
+@implementation MWMTTSLanguageViewController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ self.title = L(@"pref_tts_other_section_title");
+ self.tableView.separatorColor = [UIColor blackDividers];
+}
+
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(SettingsTableViewSelectableCell *)sender
+{
+ if (![segue.identifier isEqualToString:kUnwingSegueIdentifier])
+ return;
+ MWMTTSSettingsViewController * dest = segue.destinationViewController;
+ NSUInteger const row = [self.tableView indexPathForCell:sender].row;
+ [dest setAdditionalTTSLanguage:[[MWMTextToSpeech tts] availableLanguages][row]];
+}
+
+#pragma mark - UITableViewDataSource && UITableViewDelegate
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ return [[MWMTextToSpeech tts] availableLanguages].size();
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+ cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ auto cellId = [SettingsTableViewSelectableCell cellId];
+ auto cell = static_cast<SettingsTableViewSelectableCell *>(
+ [tableView dequeueReusableCellWithIdentifier:cellId]);
+ [cell
+ configWithTitle:@([[MWMTextToSpeech tts] availableLanguages][indexPath.row].second.c_str())];
+ return cell;
+}
+
+@end
diff --git a/iphone/Maps/Settings/MWMTTSSettingsViewController.h b/iphone/Maps/Settings/MWMTTSSettingsViewController.h
new file mode 100644
index 0000000000..f52576ce96
--- /dev/null
+++ b/iphone/Maps/Settings/MWMTTSSettingsViewController.h
@@ -0,0 +1,10 @@
+#import "MWMTableViewController.h"
+
+#include "std/string.hpp"
+#include "std/utility.hpp"
+
+@interface MWMTTSSettingsViewController : MWMTableViewController
+
+- (void)setAdditionalTTSLanguage:(pair<string, string> const &)l;
+
+@end
diff --git a/iphone/Maps/Settings/MWMTTSSettingsViewController.mm b/iphone/Maps/Settings/MWMTTSSettingsViewController.mm
new file mode 100644
index 0000000000..36c040c4a1
--- /dev/null
+++ b/iphone/Maps/Settings/MWMTTSSettingsViewController.mm
@@ -0,0 +1,205 @@
+#import "MWMTTSSettingsViewController.h"
+#import <AVFoundation/AVFoundation.h>
+#import "MWMTextToSpeech.h"
+#import "Statistics.h"
+#import "SwiftBridge.h"
+#import "UIColor+MapsMeColor.h"
+#import "WebViewController.h"
+
+#include "LocaleTranslator.h"
+
+static NSString * kSelectTTSLanguageSegueName = @"TTSLanguage";
+
+using namespace locale_translator;
+
+@interface MWMTTSSettingsViewController ()
+{
+ pair<string, string> _additionalTTSLanguage;
+ vector<pair<string, string>> _languages;
+}
+
+@property(nonatomic) BOOL isLocaleLanguageAbsent;
+
+@end
+
+@implementation MWMTTSSettingsViewController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ self.title = L(@"pref_tts_language_title");
+ self.tableView.separatorColor = [UIColor blackDividers];
+ MWMTextToSpeech * tts = [MWMTextToSpeech tts];
+
+ _languages.reserve(3);
+ auto const & v = tts.availableLanguages;
+ NSAssert(!v.empty(), @"Vector can't be empty!");
+ pair<string, string> const standart = v.front();
+ _languages.push_back(standart);
+
+ using namespace tts;
+ NSString * currentBcp47 = [AVSpeechSynthesisVoice currentLanguageCode];
+ string const currentBcp47Str = [currentBcp47 UTF8String];
+ string const currentTwineStr = bcp47ToTwineLanguage(currentBcp47);
+ if (currentBcp47Str != standart.first && !currentBcp47Str.empty())
+ {
+ string const translated = translatedTwine(currentTwineStr);
+ pair<string, string> const cur{currentBcp47Str, translated};
+ if (translated.empty() || find(v.begin(), v.end(), cur) != v.end())
+ _languages.push_back(cur);
+ else
+ self.isLocaleLanguageAbsent = YES;
+ }
+
+ NSString * nsSavedLanguage = [MWMTextToSpeech savedLanguage];
+ if (nsSavedLanguage.length)
+ {
+ string const savedLanguage = nsSavedLanguage.UTF8String;
+ if (savedLanguage != currentBcp47Str && savedLanguage != standart.first &&
+ !savedLanguage.empty())
+ _languages.emplace_back(
+ make_pair(savedLanguage, translatedTwine(bcp47ToTwineLanguage(nsSavedLanguage))));
+ }
+}
+
+- (IBAction)unwind:(id)sender
+{
+ size_t const size = _languages.size();
+ if (find(_languages.begin(), _languages.end(), _additionalTTSLanguage) != _languages.end())
+ {
+ [self.tableView reloadData];
+ return;
+ }
+ switch (size)
+ {
+ case 1: _languages.push_back(_additionalTTSLanguage); break;
+ case 2:
+ if (self.isLocaleLanguageAbsent)
+ _languages[size - 1] = _additionalTTSLanguage;
+ else
+ _languages.push_back(_additionalTTSLanguage);
+ break;
+ case 3: _languages[size - 1] = _additionalTTSLanguage; break;
+ default: NSAssert(false, @"Incorrect language's count"); break;
+ }
+ [self.tableView reloadData];
+}
+
+- (void)setAdditionalTTSLanguage:(pair<string, string> const &)l
+{
+ [[MWMTextToSpeech tts] setNotificationsLocale:@(l.first.c_str())];
+ _additionalTTSLanguage = l;
+}
+
+#pragma mark - UITableViewDataSource
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 2; }
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ if (section == 0)
+ return _languages.size() + 2;
+ else
+ return 1;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView
+ cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ if (indexPath.section == 0)
+ {
+ if (indexPath.row == 0)
+ {
+ auto cellId = [SettingsTableViewSelectableCell cellId];
+ auto cell = static_cast<SettingsTableViewSelectableCell *>(
+ [tableView dequeueReusableCellWithIdentifier:cellId]);
+ [cell configWithTitle:L(@"duration_disabled")];
+ cell.accessoryType = [MWMTextToSpeech isTTSEnabled] ? UITableViewCellAccessoryNone
+ : UITableViewCellAccessoryCheckmark;
+ return cell;
+ }
+ else
+ {
+ NSInteger const row = indexPath.row - 1;
+ if (row == _languages.size())
+ {
+ auto cellId = [SettingsTableViewLinkCell cellId];
+ auto cell = static_cast<SettingsTableViewLinkCell *>(
+ [tableView dequeueReusableCellWithIdentifier:cellId]);
+ [cell configWithTitle:L(@"pref_tts_other_section_title") info:nil];
+ return cell;
+ }
+ else
+ {
+ auto cellId = [SettingsTableViewSelectableCell cellId];
+ auto cell = static_cast<SettingsTableViewSelectableCell *>(
+ [tableView dequeueReusableCellWithIdentifier:cellId]);
+ pair<string, string> const p = _languages[row];
+ [cell configWithTitle:@(p.second.c_str())];
+ BOOL const isSelected =
+ [@(p.first.c_str()) isEqualToString:[MWMTextToSpeech savedLanguage]];
+ cell.accessoryType = [MWMTextToSpeech isTTSEnabled] && isSelected
+ ? UITableViewCellAccessoryCheckmark
+ : UITableViewCellAccessoryNone;
+ return cell;
+ }
+ }
+ }
+ else
+ {
+ auto cellId = [SettingsTableViewLinkCell cellId];
+ auto cell = static_cast<SettingsTableViewLinkCell *>(
+ [tableView dequeueReusableCellWithIdentifier:cellId]);
+ [cell configWithTitle:L(@"pref_tts_how_to_set_up_voice") info:nil];
+ return cell;
+ }
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ if (indexPath.section == 0)
+ {
+ if (indexPath.row == 0)
+ {
+ [Statistics logEvent:kStatEventName(kStatSettings, kStatTTS)
+ withParameters:@{kStatValue : kStatOff}];
+ [MWMTextToSpeech setTTSEnabled:NO];
+ [tableView reloadSections:[NSIndexSet indexSetWithIndex:0]
+ withRowAnimation:UITableViewRowAnimationFade];
+ }
+ else
+ {
+ [Statistics logEvent:kStatEventName(kStatSettings, kStatTTS)
+ withParameters:@{kStatValue : kStatOn}];
+ [MWMTextToSpeech setTTSEnabled:YES];
+ NSInteger const row = indexPath.row - 1;
+ if (row == _languages.size())
+ {
+ [Statistics logEvent:kStatEventName(kStatTTSSettings, kStatChangeLanguage)
+ withParameters:@{kStatValue : kStatOther}];
+ [self performSegueWithIdentifier:kSelectTTSLanguageSegueName sender:nil];
+ }
+ else
+ {
+ [[MWMTextToSpeech tts] setNotificationsLocale:@(_languages[row].first.c_str())];
+ [tableView reloadSections:[NSIndexSet indexSetWithIndex:0]
+ withRowAnimation:UITableViewRowAnimationFade];
+ }
+ }
+ }
+ else if (indexPath.section == 1)
+ {
+ [Statistics logEvent:kStatEventName(kStatTTSSettings, kStatHelp)];
+ NSString * path =
+ [[NSBundle mainBundle] pathForResource:@"tts-how-to-set-up-voice" ofType:@"html"];
+ NSString * html =
+ [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
+ NSURL * baseURL = [NSURL fileURLWithPath:path];
+ WebViewController * vc =
+ [[WebViewController alloc] initWithHtml:html
+ baseUrl:baseURL
+ andTitleOrNil:L(@"pref_tts_how_to_set_up_voice")];
+ [self.navigationController pushViewController:vc animated:YES];
+ }
+}
+
+@end
diff --git a/iphone/Maps/Settings/MWMUnitsController.h b/iphone/Maps/Settings/MWMUnitsController.h
new file mode 100644
index 0000000000..9135e1df1e
--- /dev/null
+++ b/iphone/Maps/Settings/MWMUnitsController.h
@@ -0,0 +1,5 @@
+#import "MWMTableViewController.h"
+
+@interface MWMUnitsController : MWMTableViewController
+
+@end
diff --git a/iphone/Maps/Settings/MWMUnitsController.mm b/iphone/Maps/Settings/MWMUnitsController.mm
new file mode 100644
index 0000000000..d82139c005
--- /dev/null
+++ b/iphone/Maps/Settings/MWMUnitsController.mm
@@ -0,0 +1,57 @@
+#import "MWMUnitsController.h"
+#import "MWMSettings.h"
+#import "Statistics.h"
+#import "SwiftBridge.h"
+
+@interface MWMUnitsController ()
+
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * kilometers;
+@property(weak, nonatomic) IBOutlet SettingsTableViewSelectableCell * miles;
+@property(weak, nonatomic) SettingsTableViewSelectableCell * selectedCell;
+
+@end
+
+@implementation MWMUnitsController
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ self.title = L(@"measurement_units");
+
+ switch ([MWMSettings measurementUnits])
+ {
+ case measurement_utils::Units::Metric: self.selectedCell = self.kilometers; break;
+ case measurement_utils::Units::Imperial: self.selectedCell = self.miles; break;
+ }
+}
+
+- (void)setSelectedCell:(SettingsTableViewSelectableCell *)cell
+{
+ SettingsTableViewSelectableCell * selectedCell = _selectedCell;
+ if (selectedCell == cell)
+ return;
+
+ selectedCell.accessoryType = UITableViewCellAccessoryNone;
+ cell.accessoryType = UITableViewCellAccessoryCheckmark;
+ cell.selected = NO;
+ _selectedCell = cell;
+ if (cell == self.kilometers)
+ {
+ [Statistics logEvent:kStatEventName(kStatSettings, kStatChangeMeasureUnits)
+ withParameters:@{kStatValue : kStatKilometers}];
+ [MWMSettings setMeasurementUnits:measurement_utils::Units::Metric];
+ }
+ else
+ {
+ [Statistics logEvent:kStatEventName(kStatSettings, kStatChangeMeasureUnits)
+ withParameters:@{kStatValue : kStatMiles}];
+ [MWMSettings setMeasurementUnits:measurement_utils::Units::Imperial];
+ }
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ self.selectedCell = [tableView cellForRowAtIndexPath:indexPath];
+}
+
+@end
diff --git a/iphone/Maps/Settings/SelectableCell.h b/iphone/Maps/Settings/SelectableCell.h
deleted file mode 100644
index d86d8819d1..0000000000
--- a/iphone/Maps/Settings/SelectableCell.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#import "MWMTableViewCell.h"
-
-@interface SelectableCell : MWMTableViewCell
-
-@property (weak, nonatomic) IBOutlet UILabel * titleLabel;
-
-@end
diff --git a/iphone/Maps/Settings/SelectableCell.mm b/iphone/Maps/Settings/SelectableCell.mm
deleted file mode 100644
index 289e5c7b23..0000000000
--- a/iphone/Maps/Settings/SelectableCell.mm
+++ /dev/null
@@ -1,12 +0,0 @@
-#import "SelectableCell.h"
-#import "UIColor+MapsMeColor.h"
-
-@implementation SelectableCell
-
-- (void)awakeFromNib
-{
- [super awakeFromNib];
- self.backgroundColor = [UIColor white];
-}
-
-@end
diff --git a/iphone/Maps/Settings/SwitchCell.h b/iphone/Maps/Settings/SwitchCell.h
deleted file mode 100644
index 8dfb1ad1c4..0000000000
--- a/iphone/Maps/Settings/SwitchCell.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#import "MWMTableViewCell.h"
-
-@class SwitchCell;
-@protocol SwitchCellDelegate <NSObject>
-
-- (void)switchCell:(SwitchCell *)cell didChangeValue:(BOOL)value;
-
-@end
-
-@interface SwitchCell : MWMTableViewCell
-
-@property(weak, nonatomic) IBOutlet UILabel * titleLabel;
-@property(weak, nonatomic) IBOutlet UISwitch * switchButton;
-
-@property(weak, nonatomic) id<SwitchCellDelegate> delegate;
-
-@end
diff --git a/iphone/Maps/Settings/SwitchCell.mm b/iphone/Maps/Settings/SwitchCell.mm
deleted file mode 100644
index 292ec81b43..0000000000
--- a/iphone/Maps/Settings/SwitchCell.mm
+++ /dev/null
@@ -1,18 +0,0 @@
-#import "SwitchCell.h"
-#import "UIColor+MapsMeColor.h"
-
-@implementation SwitchCell
-
-- (void)awakeFromNib
-{
- [super awakeFromNib];
- [self.switchButton addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
- self.backgroundColor = [UIColor white];
-}
-
-- (void)switchChanged:(UISwitch *)sender
-{
- [self.delegate switchCell:self didChangeValue:sender.on];
-}
-
-@end