forked from organicmaps/organicmaps
[ios] Create bookmark category alert.
This commit is contained in:
parent
e852f87297
commit
cc34cceaae
15 changed files with 488 additions and 18 deletions
|
@ -42,27 +42,23 @@ final class BMCViewController: MWMViewController {
|
|||
|
||||
private func updateCategoryName(category: BMCCategory?) {
|
||||
let isNewCategory = (category == nil)
|
||||
let alert = UIAlertController(title: L(isNewCategory ? "bookmarks_create_new_group" : "rename"), message: nil, preferredStyle: .alert)
|
||||
alertController.presentCreateBookmarkCategoryAlert(withMaxCharacterNum: viewModel.maxCategoryNameLength,
|
||||
minCharacterNum: viewModel.minCategoryNameLength,
|
||||
isNewCategory: isNewCategory)
|
||||
{ [weak viewModel] (name: String!) -> Bool in
|
||||
guard let model = viewModel else { return false }
|
||||
if model.checkCategory(name: name) {
|
||||
if isNewCategory {
|
||||
model.addCategory(name: name)
|
||||
} else {
|
||||
model.renameCategory(category: category!, name: name)
|
||||
}
|
||||
|
||||
alert.addTextField { textField in
|
||||
textField.placeholder = L("bookmark_set_name")
|
||||
if let category = category {
|
||||
textField.text = category.title
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
alert.addAction(UIAlertAction(title: L("cancel").capitalized, style: .cancel, handler: nil))
|
||||
alert.addAction(UIAlertAction(title: L(isNewCategory ? "create" : "ok").capitalized, style: .default) { [weak alert, viewModel] _ in
|
||||
guard let categoryName = alert?.textFields?.first?.text, !categoryName.isEmpty,
|
||||
let viewModel = viewModel else { return }
|
||||
if let category = category {
|
||||
viewModel.renameCategory(category: category, name: categoryName)
|
||||
} else {
|
||||
viewModel.addCategory(name: categoryName)
|
||||
}
|
||||
})
|
||||
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
private func shareCategory(category: BMCCategory, anchor: UIView) {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
final class BMCDefaultViewModel: NSObject {
|
||||
var view: BMCView!
|
||||
private enum Const
|
||||
{
|
||||
static let minCategoryNameLength: UInt = 0
|
||||
static let maxCategoryNameLength: UInt = 60
|
||||
}
|
||||
|
||||
private var sections: [BMCSection] = []
|
||||
private var permissions: [BMCPermission] = []
|
||||
|
@ -10,6 +15,9 @@ final class BMCDefaultViewModel: NSObject {
|
|||
private(set) var isPendingPermission = false
|
||||
private var isAuthenticated = false
|
||||
|
||||
var minCategoryNameLength: UInt = Const.minCategoryNameLength
|
||||
var maxCategoryNameLength: UInt = Const.maxCategoryNameLength
|
||||
|
||||
typealias BM = MWMBookmarksManager
|
||||
|
||||
override init() {
|
||||
|
@ -147,6 +155,10 @@ extension BMCDefaultViewModel: BMCViewModel {
|
|||
view.delete(at: IndexPath(row: row, section: section))
|
||||
}
|
||||
|
||||
func checkCategory(name: String) -> Bool {
|
||||
return BM.checkCategoryName(name)
|
||||
}
|
||||
|
||||
func beginShareCategory(category: BMCCategory) -> BMCShareCategoryStatus {
|
||||
switch BM.beginShareCategory(category.identifier) {
|
||||
case .success:
|
||||
|
|
|
@ -12,6 +12,8 @@ enum BMCShareCategoryStatus {
|
|||
protocol BMCViewModel: AnyObject {
|
||||
var view: BMCView! { get set }
|
||||
var isPendingPermission: Bool { get }
|
||||
var minCategoryNameLength: UInt { get }
|
||||
var maxCategoryNameLength: UInt { get }
|
||||
|
||||
func numberOfSections() -> Int
|
||||
func sectionType(section: Int) -> BMCSection
|
||||
|
@ -28,6 +30,7 @@ protocol BMCViewModel: AnyObject {
|
|||
func addCategory(name: String)
|
||||
func renameCategory(category: BMCCategory, name: String)
|
||||
func deleteCategory(category: BMCCategory)
|
||||
func checkCategory(name: String) -> Bool
|
||||
|
||||
func beginShareCategory(category: BMCCategory) -> BMCShareCategoryStatus
|
||||
func endShareCategory(category: BMCCategory)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@interface UIFont (MapsMeFonts)
|
||||
|
||||
+ (UIFont *)regular10;
|
||||
+ (UIFont *)regular11;
|
||||
+ (UIFont *)regular12;
|
||||
+ (UIFont *)regular13;
|
||||
+ (UIFont *)regular14;
|
||||
|
|
|
@ -6,6 +6,7 @@ NSString * const kLightFontName = @"HelveticaNeue-Light";
|
|||
@implementation UIFont (MapsMeFonts)
|
||||
|
||||
+ (UIFont *)regular10 { return [UIFont systemFontOfSize:10]; }
|
||||
+ (UIFont *)regular11 { return [UIFont systemFontOfSize:11]; }
|
||||
+ (UIFont *)regular12 { return [UIFont systemFontOfSize:12]; }
|
||||
+ (UIFont *)regular13 { return [UIFont systemFontOfSize:13]; }
|
||||
+ (UIFont *)regular14 { return [UIFont systemFontOfSize:14]; }
|
||||
|
|
|
@ -44,6 +44,11 @@
|
|||
- (void)presentSearchNoResultsAlert;
|
||||
- (void)presentMobileInternetAlertWithBlock:(nonnull MWMVoidBlock)block;
|
||||
- (void)presentInfoAlert:(nonnull NSString *)title text:(nonnull NSString *)text;
|
||||
- (void)presentCreateBookmarkCategoryAlertWithMaxCharacterNum:(NSUInteger)max
|
||||
minCharacterNum:(NSUInteger)min
|
||||
isNewCategory:(BOOL)isNewCategory
|
||||
callback:(nonnull MWMCheckStringBlock)callback;
|
||||
|
||||
- (void)closeAlert:(nullable MWMVoidBlock)completion;
|
||||
|
||||
- (nonnull instancetype)init __attribute__((unavailable("call -initWithViewController: instead!")));
|
||||
|
|
|
@ -215,6 +215,23 @@ static NSString * const kAlertControllerNibIdentifier = @"MWMAlertViewController
|
|||
|
||||
- (void)presentEditorViralAlert { [self displayAlert:[MWMAlert editorViralAlert]]; }
|
||||
- (void)presentOsmAuthAlert { [self displayAlert:[MWMAlert osmAuthAlert]]; }
|
||||
|
||||
- (void)presentCreateBookmarkCategoryAlertWithMaxCharacterNum:(NSUInteger)max
|
||||
minCharacterNum:(NSUInteger)min
|
||||
isNewCategory:(BOOL)isNewCategory
|
||||
callback:(nonnull MWMCheckStringBlock)callback
|
||||
{
|
||||
auto alert = static_cast<MWMBCCreateCategoryAlert *>([MWMAlert
|
||||
createBookmarkCategoryAlertWithMaxCharacterNum:max
|
||||
minCharacterNum:min
|
||||
isNewCategory:isNewCategory
|
||||
callback:callback]);
|
||||
[self displayAlert:alert];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[alert.textField becomeFirstResponder];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)displayAlert:(MWMAlert *)alert
|
||||
{
|
||||
// TODO(igrechuhin): Remove this check on location manager refactoring.
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
+ (MWMAlert *)personalInfoWarningAlertWithBlock:(MWMVoidBlock)block;
|
||||
+ (MWMAlert *)trackWarningAlertWithCancelBlock:(MWMVoidBlock)block;
|
||||
+ (MWMAlert *)infoAlert:(NSString *)title text:(NSString *)text;
|
||||
+ (MWMAlert *)createBookmarkCategoryAlertWithMaxCharacterNum:(NSUInteger)max
|
||||
minCharacterNum:(NSUInteger)min
|
||||
isNewCategory:(BOOL)isNewCategory
|
||||
callback:(MWMCheckStringBlock)callback;
|
||||
- (void)close:(MWMVoidBlock)completion;
|
||||
|
||||
- (void)setNeedsCloseAlertAfterEnterBackground;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#import "MWMRateAlert.h"
|
||||
#import "MWMRoutingDisclaimerAlert.h"
|
||||
|
||||
#import "SwiftBridge.h"
|
||||
|
||||
@implementation MWMAlert
|
||||
|
||||
+ (MWMAlert *)rateAlert { return [MWMRateAlert alert]; }
|
||||
|
@ -157,6 +159,17 @@
|
|||
return [MWMDefaultAlert infoAlert:title text:text];
|
||||
}
|
||||
|
||||
+ (MWMAlert *)createBookmarkCategoryAlertWithMaxCharacterNum:(NSUInteger)max
|
||||
minCharacterNum:(NSUInteger)min
|
||||
isNewCategory:(BOOL)isNewCategory
|
||||
callback:(MWMCheckStringBlock)callback
|
||||
{
|
||||
return [MWMBCCreateCategoryAlert alertWithMaxCharachersNum:max
|
||||
minCharactersNum:min
|
||||
isNewCategory:isNewCategory
|
||||
callback:callback];
|
||||
}
|
||||
|
||||
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
|
||||
{
|
||||
// Should override this method if you want custom relayout after rotation.
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
@objc(MWMBCCreateCategoryAlert)
|
||||
final class BCCreateCategoryAlert: MWMAlert {
|
||||
private enum State {
|
||||
case valid
|
||||
case tooFewSymbols
|
||||
case tooManySymbols
|
||||
case nameAlreadyExists
|
||||
}
|
||||
|
||||
@IBOutlet private(set) weak var textField: UITextField!
|
||||
@IBOutlet private weak var titleLabel: UILabel!
|
||||
@IBOutlet private weak var textFieldContainer: UIView!
|
||||
@IBOutlet private weak var centerHorizontaly: NSLayoutConstraint!
|
||||
@IBOutlet private weak var errorLabel: UILabel!
|
||||
@IBOutlet private weak var charactersCountLabel: UILabel!
|
||||
@IBOutlet private weak var rightButton: UIButton! {
|
||||
didSet {
|
||||
rightButton.setTitleColor(UIColor.blackHintText(), for: .disabled)
|
||||
}
|
||||
}
|
||||
|
||||
private var maxCharactersNum: UInt?
|
||||
private var minCharactersNum: UInt?
|
||||
private var callback: MWMCheckStringBlock?
|
||||
|
||||
@objc static func alert(maxCharachersNum: UInt,
|
||||
minCharactersNum: UInt,
|
||||
isNewCategory: Bool,
|
||||
callback: @escaping MWMCheckStringBlock) -> BCCreateCategoryAlert? {
|
||||
guard let alert = Bundle.main.loadNibNamed(className(), owner: nil, options: nil)?.first
|
||||
as? BCCreateCategoryAlert else {
|
||||
assertionFailure()
|
||||
return nil
|
||||
}
|
||||
|
||||
alert.titleLabel.text = L(isNewCategory ? "bookmarks_create_new_group" : "rename")
|
||||
let text = L(isNewCategory ? "create" : "ok").capitalized
|
||||
for s in [.normal, .highlighted, .disabled] as [UIControlState] {
|
||||
alert.rightButton.setTitle(text, for: s)
|
||||
}
|
||||
|
||||
alert.maxCharactersNum = maxCharachersNum
|
||||
alert.minCharactersNum = minCharactersNum
|
||||
alert.callback = callback
|
||||
alert.process(state: .tooFewSymbols)
|
||||
alert.formatCharactersCountText()
|
||||
MWMKeyboard.add(alert)
|
||||
return alert
|
||||
}
|
||||
|
||||
@IBAction private func leftButtonTap() {
|
||||
MWMKeyboard.remove(self)
|
||||
close(nil)
|
||||
}
|
||||
|
||||
@IBAction private func rightButtonTap() {
|
||||
guard let callback = callback, let text = textField.text else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
if callback(text) {
|
||||
MWMKeyboard.remove(self)
|
||||
close(nil)
|
||||
} else {
|
||||
process(state: .nameAlreadyExists)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction private func editingChanged(sender: UITextField) {
|
||||
formatCharactersCountText()
|
||||
process(state: checkState())
|
||||
}
|
||||
|
||||
private func checkState() -> State {
|
||||
let count = textField.text!.count
|
||||
if count <= minCharactersNum! {
|
||||
return .tooFewSymbols
|
||||
}
|
||||
|
||||
if count > maxCharactersNum! {
|
||||
return .tooManySymbols
|
||||
}
|
||||
|
||||
return .valid
|
||||
}
|
||||
|
||||
private func process(state: State) {
|
||||
let color: UIColor
|
||||
switch state {
|
||||
case .valid:
|
||||
color = UIColor.blackHintText()
|
||||
rightButton.isEnabled = true
|
||||
errorLabel.isHidden = true
|
||||
case .tooFewSymbols:
|
||||
color = UIColor.blackHintText()
|
||||
errorLabel.isHidden = true
|
||||
rightButton.isEnabled = false
|
||||
case .tooManySymbols:
|
||||
color = UIColor.buttonRed()
|
||||
errorLabel.isHidden = false
|
||||
errorLabel.text = L("bookmarks_error_title_list_name_too_long")
|
||||
rightButton.isEnabled = false
|
||||
case .nameAlreadyExists:
|
||||
color = UIColor.buttonRed()
|
||||
errorLabel.isHidden = false
|
||||
errorLabel.text = L("bookmarks_error_title_list_name_already_taken")
|
||||
rightButton.isEnabled = false
|
||||
}
|
||||
|
||||
charactersCountLabel.textColor = color
|
||||
textFieldContainer.layer.borderColor = color.cgColor
|
||||
}
|
||||
|
||||
private func formatCharactersCountText() {
|
||||
let count = textField.text!.count
|
||||
charactersCountLabel.text = String(count) + " / " + String(maxCharactersNum!)
|
||||
}
|
||||
}
|
||||
|
||||
extension BCCreateCategoryAlert: UITextFieldDelegate {
|
||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
if checkState() == .valid {
|
||||
rightButtonTap()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func textField(_ textField: UITextField,
|
||||
shouldChangeCharactersIn range: NSRange,
|
||||
replacementString string: String) -> Bool {
|
||||
let str = textField.text as NSString?
|
||||
let newStr = str?.replacingCharacters(in: range, with: string)
|
||||
guard let count = newStr?.count else {
|
||||
return true
|
||||
}
|
||||
|
||||
if count > maxCharactersNum! + 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension BCCreateCategoryAlert: MWMKeyboardObserver {
|
||||
func onKeyboardAnimation() {
|
||||
centerHorizontaly.constant -= MWMKeyboard.keyboardHeight() / 2
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
func onKeyboardWillAnimate() {
|
||||
setNeedsLayout()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<customFonts key="customFonts">
|
||||
<array key="HelveticaNeue.ttc">
|
||||
<string>HelveticaNeue</string>
|
||||
<string>HelveticaNeue-Medium</string>
|
||||
</array>
|
||||
</customFonts>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="QQB-Ml-wwB" customClass="MWMBCCreateCategoryAlert" propertyAccessControl="none">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QG2-Qb-EKf" userLabel="ContainerView">
|
||||
<rect key="frame" x="47.5" y="248" width="280" height="171.5"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4T3-au-6h5" userLabel="Title">
|
||||
<rect key="frame" x="20" y="20" width="240" height="21.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="240" id="4gN-jJ-fkn"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="20" id="dpW-YS-s4x"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Medium" family="Helvetica Neue" pointSize="18"/>
|
||||
<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="medium18"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="bookmarks_create_new_group"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="otE-Ct-TPM">
|
||||
<rect key="frame" x="16" y="61.5" width="248" height="28"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="xlp-ke-FxI">
|
||||
<rect key="frame" x="4" y="0.0" width="240" height="28"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="240" id="T3H-0E-q2e"/>
|
||||
</constraints>
|
||||
<edgeInsets key="layoutMargins" top="4" left="4" bottom="4" right="4"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences" autocorrectionType="no" returnKeyType="done" textContentType="name"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular14"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedPlaceholder" value="bookmark_set_name"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="_placeholderLabel.colorName" value="blackHintText"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="editingChangedWithSender:" destination="QQB-Ml-wwB" eventType="editingChanged" id="Rab-rj-UaD"/>
|
||||
<outlet property="delegate" destination="QQB-Ml-wwB" id="7Hk-7k-Biw"/>
|
||||
</connections>
|
||||
</textField>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="28" id="497-yd-ibe"/>
|
||||
<constraint firstItem="xlp-ke-FxI" firstAttribute="centerY" secondItem="otE-Ct-TPM" secondAttribute="centerY" id="LK1-93-zgY"/>
|
||||
<constraint firstAttribute="width" constant="248" id="hLe-SE-FJ2"/>
|
||||
<constraint firstItem="xlp-ke-FxI" firstAttribute="centerX" secondItem="otE-Ct-TPM" secondAttribute="centerX" id="sOC-II-DCo"/>
|
||||
<constraint firstItem="xlp-ke-FxI" firstAttribute="height" secondItem="otE-Ct-TPM" secondAttribute="height" id="tj3-TS-dmp"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="color" keyPath="layer.borderUIColor">
|
||||
<color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.12" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.borderWidth">
|
||||
<real key="value" value="0.5"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uxx-Di-f1Q" userLabel="hDivider">
|
||||
<rect key="frame" x="0.0" y="127.5" width="280" height="1"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.12" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="9Ur-cw-cWk"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="blackDividers"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wxi-5V-caq" userLabel="left">
|
||||
<rect key="frame" x="0.0" y="127.5" width="140" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="140" id="PcO-3k-jAQ"/>
|
||||
<constraint firstAttribute="height" constant="44" id="sIn-W3-LqB"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
|
||||
<state key="normal" title="left">
|
||||
<color key="titleColor" red="0.090196078430000007" green="0.61960784310000006" blue="0.30196078430000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<state key="highlighted" backgroundImage="dialog_btn_press"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="cancel"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="linkBlue"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium17"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="leftButtonTap" destination="QQB-Ml-wwB" eventType="touchUpInside" id="q1X-dI-dSs"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eg6-8K-8yh" userLabel="right">
|
||||
<rect key="frame" x="140" y="127.5" width="140" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="Pk8-S5-m8D"/>
|
||||
<constraint firstAttribute="width" constant="140" id="m9E-k8-sQh"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Medium" family="Helvetica Neue" pointSize="17"/>
|
||||
<state key="normal" title="right">
|
||||
<color key="titleColor" red="0.090196078430000007" green="0.61960784310000006" blue="0.30196078430000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<state key="highlighted" backgroundImage="dialog_btn_press"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="localizedText" value="create"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="linkBlue"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="medium17"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<action selector="rightButtonTap" destination="QQB-Ml-wwB" eventType="touchUpInside" id="HT2-dB-W2f"/>
|
||||
</connections>
|
||||
</button>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QQD-2O-DHw" userLabel="vDivider">
|
||||
<rect key="frame" x="139" y="127.5" width="1" height="44"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.12" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="1" id="Lhw-ff-5Vq"/>
|
||||
<constraint firstAttribute="height" constant="44" id="eaZ-L1-nnD"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="blackDividers"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="This name is too long" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dX9-2y-ZEd" userLabel="Error label">
|
||||
<rect key="frame" x="16" y="95.5" width="112" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="W4K-74-Pug"/>
|
||||
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="198" id="uYL-oU-tYf"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular11"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="buttonRed"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="750" verticalHuggingPriority="251" text="69 / 60" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WKj-KX-xnU" userLabel="Count label">
|
||||
<rect key="frame" x="225.5" y="95.5" width="38.5" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="aJd-wn-gwl"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular11"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="buttonRed"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="4T3-au-6h5" firstAttribute="top" secondItem="QG2-Qb-EKf" secondAttribute="top" constant="20" id="2l5-Sp-9hA"/>
|
||||
<constraint firstItem="dX9-2y-ZEd" firstAttribute="top" secondItem="otE-Ct-TPM" secondAttribute="bottom" constant="6" id="3N9-5v-z4Y"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Wxi-5V-caq" secondAttribute="bottom" id="3Ze-v3-100"/>
|
||||
<constraint firstAttribute="trailing" secondItem="eg6-8K-8yh" secondAttribute="trailing" id="6oa-ch-DMu"/>
|
||||
<constraint firstItem="Wxi-5V-caq" firstAttribute="leading" secondItem="QG2-Qb-EKf" secondAttribute="leading" id="6v3-kv-oqt"/>
|
||||
<constraint firstItem="uxx-Di-f1Q" firstAttribute="top" secondItem="dX9-2y-ZEd" secondAttribute="bottom" constant="12" id="7Bf-UJ-7mU"/>
|
||||
<constraint firstItem="uxx-Di-f1Q" firstAttribute="centerX" secondItem="QG2-Qb-EKf" secondAttribute="centerX" id="CSk-xb-Fd3"/>
|
||||
<constraint firstAttribute="width" constant="280" id="CwP-uI-Ukp"/>
|
||||
<constraint firstItem="uxx-Di-f1Q" firstAttribute="width" secondItem="QG2-Qb-EKf" secondAttribute="width" id="Fcb-Hq-n6a"/>
|
||||
<constraint firstItem="otE-Ct-TPM" firstAttribute="top" secondItem="4T3-au-6h5" secondAttribute="bottom" constant="20" id="NAI-NR-TFE"/>
|
||||
<constraint firstItem="otE-Ct-TPM" firstAttribute="centerX" secondItem="QG2-Qb-EKf" secondAttribute="centerX" id="Y2k-u1-PgF"/>
|
||||
<constraint firstItem="Wxi-5V-caq" firstAttribute="top" secondItem="uxx-Di-f1Q" secondAttribute="bottom" constant="-1" id="Yo8-tt-8Q6"/>
|
||||
<constraint firstAttribute="trailing" secondItem="WKj-KX-xnU" secondAttribute="trailing" constant="16" id="aRt-r1-EwI"/>
|
||||
<constraint firstItem="4T3-au-6h5" firstAttribute="centerX" secondItem="QG2-Qb-EKf" secondAttribute="centerX" id="cTf-xg-SpW"/>
|
||||
<constraint firstItem="dX9-2y-ZEd" firstAttribute="leading" secondItem="QG2-Qb-EKf" secondAttribute="leading" constant="16" id="gyf-Hq-FLl"/>
|
||||
<constraint firstItem="QQD-2O-DHw" firstAttribute="centerX" secondItem="QG2-Qb-EKf" secondAttribute="centerX" id="sUU-uz-fhn"/>
|
||||
<constraint firstAttribute="bottom" secondItem="QQD-2O-DHw" secondAttribute="bottom" id="vgE-JK-Ong"/>
|
||||
<constraint firstAttribute="bottom" secondItem="eg6-8K-8yh" secondAttribute="bottom" id="vzg-UL-heQ"/>
|
||||
<constraint firstItem="WKj-KX-xnU" firstAttribute="top" secondItem="otE-Ct-TPM" secondAttribute="bottom" constant="6" id="zK8-7y-xuI"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="size" keyPath="layer.shadowOffset">
|
||||
<size key="value" width="0.0" height="3"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="color" keyPath="layer.shadowUIColor">
|
||||
<color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.22" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.shadowRadius">
|
||||
<integer key="value" value="6"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
<integer key="value" value="12"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.shadowOpacity">
|
||||
<integer key="value" value="1"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="alertBackground"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="QG2-Qb-EKf" firstAttribute="centerY" secondItem="QQB-Ml-wwB" secondAttribute="centerY" id="od7-2i-rqy"/>
|
||||
<constraint firstItem="QG2-Qb-EKf" firstAttribute="centerX" secondItem="QQB-Ml-wwB" secondAttribute="centerX" id="zjO-HS-7Up"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="oQA-N9-AkF"/>
|
||||
<connections>
|
||||
<outlet property="centerHorizontaly" destination="od7-2i-rqy" id="lVF-DA-PUg"/>
|
||||
<outlet property="charactersCountLabel" destination="WKj-KX-xnU" id="X0L-zL-ZcF"/>
|
||||
<outlet property="errorLabel" destination="dX9-2y-ZEd" id="XLx-WJ-h4h"/>
|
||||
<outlet property="rightButton" destination="eg6-8K-8yh" id="YGF-Zh-u1y"/>
|
||||
<outlet property="textField" destination="xlp-ke-FxI" id="pBV-Ne-ekt"/>
|
||||
<outlet property="textFieldContainer" destination="otE-Ct-TPM" id="Nf8-ly-qdn"/>
|
||||
<outlet property="titleLabel" destination="4T3-au-6h5" id="ye3-HE-xqN"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="304.5" y="171.5"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="dialog_btn_press" width="280" height="44"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -1,6 +1,7 @@
|
|||
typedef void (^MWMVoidBlock)(void);
|
||||
typedef void (^MWMStringBlock)(NSString *);
|
||||
typedef void (^MWMURLBlock)(NSURL *);
|
||||
typedef BOOL (^MWMCheckStringBlock)(NSString *);
|
||||
|
||||
typedef NS_ENUM(NSUInteger, MWMDayTime) { MWMDayTimeDay, MWMDayTimeNight };
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
+ (void)deleteCategory:(MWMMarkGroupID)groupId;
|
||||
|
||||
+ (void)deleteBookmark:(MWMMarkID)bookmarkId;
|
||||
+ (BOOL)checkCategoryName:(NSString *)name;
|
||||
|
||||
+ (MWMBookmarksShareStatus)beginShareCategory:(MWMMarkGroupID)groupId;
|
||||
+ (NSURL *)shareCategoryURL;
|
||||
|
|
|
@ -183,6 +183,11 @@ using TLoopBlock = void (^)(Observer observer);
|
|||
}];
|
||||
}
|
||||
|
||||
+ (BOOL)checkCategoryName:(NSString *)name
|
||||
{
|
||||
return !GetFramework().GetBookmarkManager().IsUsedCategoryName(name.UTF8String);
|
||||
}
|
||||
|
||||
+ (MWMBookmarksShareStatus)beginShareCategory:(MWMMarkGroupID)groupId
|
||||
{
|
||||
auto const sharingResult = GetFramework().GetBookmarkManager().BeginSharing(groupId);
|
||||
|
|
|
@ -512,6 +512,8 @@
|
|||
F6BD1D211CA412920047B8E8 /* MWMOsmAuthAlert.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6BD1D1F1CA412920047B8E8 /* MWMOsmAuthAlert.mm */; };
|
||||
F6BD1D241CA412E40047B8E8 /* MWMOsmAuthAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = F6BD1D221CA412E30047B8E8 /* MWMOsmAuthAlert.xib */; };
|
||||
F6C16A671F9626B2000FE296 /* ReviewsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3430291B1F87BC3000D0A07C /* ReviewsViewController.xib */; };
|
||||
F6D67CDC2062B9C00032FD38 /* BCCreateCategoryAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6D67CDB2062B9C00032FD38 /* BCCreateCategoryAlert.swift */; };
|
||||
F6D67CDE2062BBA60032FD38 /* MWMBCCreateCategoryAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = F6D67CDD2062BBA60032FD38 /* MWMBCCreateCategoryAlert.xib */; };
|
||||
F6E2FD501E097BA00083EBEC /* MWMMapDownloaderAdsTableViewCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6E2FBFF1E097B9F0083EBEC /* MWMMapDownloaderAdsTableViewCell.mm */; };
|
||||
F6E2FD531E097BA00083EBEC /* MWMMapDownloaderAdsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F6E2FC001E097B9F0083EBEC /* MWMMapDownloaderAdsTableViewCell.xib */; };
|
||||
F6E2FD561E097BA00083EBEC /* MWMMapDownloaderButtonTableViewCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6E2FC021E097B9F0083EBEC /* MWMMapDownloaderButtonTableViewCell.mm */; };
|
||||
|
@ -1433,6 +1435,8 @@
|
|||
F6BD1D1E1CA412920047B8E8 /* MWMOsmAuthAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMOsmAuthAlert.h; sourceTree = "<group>"; };
|
||||
F6BD1D1F1CA412920047B8E8 /* MWMOsmAuthAlert.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = MWMOsmAuthAlert.mm; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
F6BD1D221CA412E30047B8E8 /* MWMOsmAuthAlert.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MWMOsmAuthAlert.xib; sourceTree = "<group>"; };
|
||||
F6D67CDB2062B9C00032FD38 /* BCCreateCategoryAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BCCreateCategoryAlert.swift; sourceTree = "<group>"; };
|
||||
F6D67CDD2062BBA60032FD38 /* MWMBCCreateCategoryAlert.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MWMBCCreateCategoryAlert.xib; sourceTree = "<group>"; };
|
||||
F6DF5F321CD1136800A87154 /* LocaleTranslator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocaleTranslator.h; sourceTree = "<group>"; };
|
||||
F6E2FBFE1E097B9F0083EBEC /* MWMMapDownloaderAdsTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMMapDownloaderAdsTableViewCell.h; sourceTree = "<group>"; };
|
||||
F6E2FBFF1E097B9F0083EBEC /* MWMMapDownloaderAdsTableViewCell.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMMapDownloaderAdsTableViewCell.mm; sourceTree = "<group>"; };
|
||||
|
@ -3054,6 +3058,7 @@
|
|||
F64F195F1AB8125C006EAF7E /* CustomAlert */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F6D67CDA2062B9810032FD38 /* CreateBookmarkCategory */,
|
||||
349B92691DF0516C007779DD /* Toast */,
|
||||
349A137E1DEC138C00C7DB60 /* MobileInternetAlert */,
|
||||
3462258B1DDC5D76001E8752 /* SearchAlert */,
|
||||
|
@ -3241,6 +3246,15 @@
|
|||
name = AuthAlert;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F6D67CDA2062B9810032FD38 /* CreateBookmarkCategory */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F6D67CDB2062B9C00032FD38 /* BCCreateCategoryAlert.swift */,
|
||||
F6D67CDD2062BBA60032FD38 /* MWMBCCreateCategoryAlert.xib */,
|
||||
);
|
||||
path = CreateBookmarkCategory;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F6E2FBFB1E097B9F0083EBEC /* UI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -4190,6 +4204,7 @@
|
|||
F6E2FF421E097BA00083EBEC /* MWMSearchTableViewController.xib in Resources */,
|
||||
34AB66681FC5AA330078E451 /* TransportTransitPedestrian.xib in Resources */,
|
||||
F6E2FEEE1E097BA00083EBEC /* MWMSearchView.xib in Resources */,
|
||||
F6D67CDE2062BBA60032FD38 /* MWMBCCreateCategoryAlert.xib in Resources */,
|
||||
344532511F714FD70059FBCC /* UGCAddReviewController.xib in Resources */,
|
||||
3490D2E31CE9DD2500D0B838 /* MWMSideButtonsView.xib in Resources */,
|
||||
346DB82B1E5C4F6700E3123E /* GalleryCell.xib in Resources */,
|
||||
|
@ -4634,6 +4649,7 @@
|
|||
3430291D1F87BF4400D0A07C /* ReviewsViewController.swift in Sources */,
|
||||
F6E2FE731E097BA00083EBEC /* MWMOpeningHours.mm in Sources */,
|
||||
3404F4842028908C0090E401 /* AddSetTableViewCell.mm in Sources */,
|
||||
F6D67CDC2062B9C00032FD38 /* BCCreateCategoryAlert.swift in Sources */,
|
||||
F6E2FF601E097BA00083EBEC /* MWMSettingsViewController.mm in Sources */,
|
||||
F6E2FE2B1E097BA00083EBEC /* MWMStreetEditorEditTableViewCell.mm in Sources */,
|
||||
34AB66891FC5AA330078E451 /* NavigationControlView.swift in Sources */,
|
||||
|
|
Loading…
Add table
Reference in a new issue