[ios] Add a products section to the place page #8638
56 changed files with 791 additions and 3 deletions
|
@ -6868,6 +6868,143 @@
|
|||
zh-Hans = 捐助,以共同打造最好的地图!
|
||||
zh-Hant = 捐助,以共同打造最好的地圖!
|
||||
|
||||
[already_donated]
|
||||
tags = ios
|
||||
en = Already donated
|
||||
af = Reeds geskenk
|
||||
ar = تم التبرع
|
||||
az = Artıq ianə edildi
|
||||
be = Ужо ахвяравана
|
||||
bg = Вече дарено
|
||||
ca = Ja donat
|
||||
cs = Již darováno
|
||||
da = Allerede doneret
|
||||
de = Bereits gespendet
|
||||
map-per
commented
Review
```suggestion
de = Bereits gespendet
```
|
||||
el = Ήδη δωρεά
|
||||
es = Ya donado
|
||||
et = Juba annetatud
|
||||
eu = Dohaintza jada emana
|
||||
![]() eu = Dohaintza jada emana eu = Dohaintza jada emana
|
||||
fa = قبلاً اهدا شده
|
||||
fi = Jo lahjoitettu
|
||||
fr = Déjà donné
|
||||
he = כבר נתרם
|
||||
hi = पहले से दान
|
||||
hu = Már adományozva
|
||||
id = Sudah disumbang
|
||||
it = Già donato
|
||||
ja = 寄付済み
|
||||
ko = 기부완료
|
||||
lt = Jau noziedoju
|
||||
![]() Latvian was omitted lv = Jau noziedoju Latvian was omitted
lv = Jau noziedoju
|
||||
mr = आधीच दान केले
|
||||
nb = Allerede donert
|
||||
nl = Reeds gedoneerd
|
||||
pl = Już przekazano
|
||||
pt = Já doado
|
||||
pt-BR = Já doado
|
||||
ro = Deja donat
|
||||
ru = Уже пожертвовано
|
||||
![]() Уже задонатил? Уже задонатил?
pastk
commented
не подходит для женщин, надо нейтрально не подходит для женщин, надо нейтрально
"Уже пожертвовано"
поэтому нормально
rtsisyk
commented
Пожертвовано - это про церковь. Пожертвовано - это про церковь.
![]() А можно нормальным русским языком без вот этих "донатов"? 🍩 "Пожертвование" и "благотворительность" — абсолютно нормальные слова и не обязательно сразу церковь. А можно нормальным русским языком без вот этих "донатов"? 🍩
"Пожертвование" и "благотворительность" — абсолютно нормальные слова и не обязательно сразу церковь.
|
||||
sk = Už darované
|
||||
sv = Redan donerat
|
||||
sw = Tayari kutoa
|
||||
th = บริจาคแล้ว
|
||||
tr = Zaten bağışlandı
|
||||
uk = Вже пожертвувано
|
||||
vi = Đã quyên góp
|
||||
zh-Hans = 已捐赠
|
||||
zh-Hant = 已捐贈
|
||||
|
||||
[remind_me_later]
|
||||
tags = ios
|
||||
en = Remind later
|
||||
af = Herinner later
|
||||
ar = ذكر لاحقاً
|
||||
az = Daha sonra xatırlat
|
||||
be = Нагадаць пазней
|
||||
bg = Напомни по-късно
|
||||
ca = Recorda més tard
|
||||
cs = Připomeň později
|
||||
da = Mind mig senere
|
||||
de = Später erinnern
|
||||
map-per
commented
```suggestion
de = Später erinnern
```
|
||||
el = Υπενθύμισε αργότερα
|
||||
es = Recordar más tarde
|
||||
et = Meenuta hiljem
|
||||
eu = Gogoratu geroago
|
||||
fa = بعداً یادآوری کن
|
||||
fi = Muistuta myöhemmin
|
||||
fr = Rappeler plus tard
|
||||
he = הזכר מאוחר יותר
|
||||
hi = बाद में याद दिलाना
|
||||
hu = Emlékeztessen később
|
||||
id = Ingatkan nanti
|
||||
it = Ricorda più tardi
|
||||
ja = 後でリマインド
|
||||
ko = 나중에 알림
|
||||
lt = Priminti vėliau
|
||||
lv = Atgādināt vēlāk
|
||||
mr = नंतर आठवण करून द्या
|
||||
nb = Påminn senere
|
||||
nl = Herinner later
|
||||
pl = Przypomnij później
|
||||
pt = Lembrar mais tarde
|
||||
pt-BR = Lembrar mais tarde
|
||||
ro = Amintește mai târziu
|
||||
ru = Напомнить позже
|
||||
sk = Pripomeň neskôr
|
||||
sv = Påminn senare
|
||||
sw = Kumbusha baadaye
|
||||
th = เตือนภายหลัง
|
||||
tr = Sonra hatırlat
|
||||
uk = Нагадати пізніше
|
||||
vi = Nhắc sau
|
||||
zh-Hans = 稍后提醒
|
||||
zh-Hant = 稍後提醒
|
||||
|
||||
[support_organic_maps]
|
||||
tags = ios
|
||||
en = Support Organic Maps
|
||||
af = Ondersteun Organic Maps
|
||||
ar = دعم Organic Maps
|
||||
az = Organic Maps-i dəstəkləmək
|
||||
be = Падтрымаць Organic Maps
|
||||
bg = Подкрепи Organic Maps
|
||||
ca = Donar suport a Organic Maps
|
||||
cs = Podpořit Organic Maps
|
||||
da = Støtte Organic Maps
|
||||
de = Organic Maps unterstützen
|
||||
el = Υποστήριξε το Organic Maps
|
||||
es = Apoyar Organic Maps
|
||||
et = Toetada Organic Maps
|
||||
eu = Sustatu Organic Maps
|
||||
![]() eu = Sustatu Organic Maps eu = Sustatu Organic Maps
|
||||
fa = پشتیبانی از Organic Maps
|
||||
fi = Tukea Organic Maps
|
||||
fr = Soutenir Organic Maps
|
||||
he = לתמוך ב-Organic Maps
|
||||
hi = Organic Maps का समर्थन करें
|
||||
hu = Organic Maps támogatása
|
||||
id = Mendukung Organic Maps
|
||||
it = Supportare Organic Maps
|
||||
ja = Organic Maps を支援
|
||||
ko = Organic Maps 지원하기
|
||||
lt = Paremti Organic Maps
|
||||
lv = Atbalstīt Organic Maps
|
||||
mr = Organic Maps ला समर्थन द्या
|
||||
nb = Støtte Organic Maps
|
||||
nl = Ondersteun Organic Maps
|
||||
![]()
```suggestion
nl = Ondersteun Organic Maps
```
|
||||
pl = Wspierać Organic Maps
|
||||
pt = Apoiar Organic Maps
|
||||
pt-BR = Apoiar Organic Maps
|
||||
ro = Susține Organic Maps
|
||||
ru = Поддержать Organic Maps
|
||||
sk = Podporiť Organic Maps
|
||||
sv = Stödja Organic Maps
|
||||
sw = Kuunga mkono Organic Maps
|
||||
th = สนับสนุน Organic Maps
|
||||
tr = Organic Maps’i Desteklemek
|
||||
uk = Підтримати Organic Maps
|
||||
vi = Hỗ trợ Organic Maps
|
||||
zh-Hans = 支持 Organic Maps
|
||||
zh-Hant = 支持 Organic Maps
|
||||
|
||||
[how_to_support_us]
|
||||
comment = Button in the main Help dialog
|
||||
tags = android
|
||||
|
|
|
@ -87,6 +87,11 @@
|
|||
AC6A585728057EF6003EABAF /* StringUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = AC6A585628057CC1003EABAF /* StringUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
ED0B1FF42CAAE3FF006E31A4 /* DeepLinkInAppFeatureHighlightData.h in Headers */ = {isa = PBXBuildFile; fileRef = ED0B1FF22CAAE3FF006E31A4 /* DeepLinkInAppFeatureHighlightData.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
ED0B1FF52CAAE3FF006E31A4 /* DeepLinkInAppFeatureHighlightData.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED0B1FF32CAAE3FF006E31A4 /* DeepLinkInAppFeatureHighlightData.mm */; };
|
||||
ED49D7222CED0395004AF27E /* ProductsConfiguration+Core.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED49D7202CED0395004AF27E /* ProductsConfiguration+Core.mm */; };
|
||||
ED49D7242CED03AC004AF27E /* ProductsConfiguration+Core.h in Headers */ = {isa = PBXBuildFile; fileRef = ED49D7232CED03A8004AF27E /* ProductsConfiguration+Core.h */; };
|
||||
ED49D75B2CEF8BD2004AF27E /* ProductsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED49D7562CEF850F004AF27E /* ProductsConfiguration.swift */; };
|
||||
ED49D75F2CEFA8C0004AF27E /* Product+Core.h in Headers */ = {isa = PBXBuildFile; fileRef = ED49D75E2CEFA8C0004AF27E /* Product+Core.h */; };
|
||||
ED49D7612CEFA8E1004AF27E /* Product+Core.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED49D7602CEFA8E1004AF27E /* Product+Core.mm */; };
|
||||
ED965B0D2CD67A470049E39E /* DistanceFormatter.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED965B0A2CD67A470049E39E /* DistanceFormatter.mm */; };
|
||||
ED965B102CD67A470049E39E /* DistanceFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = ED965B092CD67A470049E39E /* DistanceFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
ED965B132CD67A9B0049E39E /* AltitudeFormatter.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED965B122CD67A9B0049E39E /* AltitudeFormatter.mm */; };
|
||||
|
@ -187,6 +192,11 @@
|
|||
AC6A585628057CC1003EABAF /* StringUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringUtils.h; sourceTree = "<group>"; };
|
||||
ED0B1FF22CAAE3FF006E31A4 /* DeepLinkInAppFeatureHighlightData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeepLinkInAppFeatureHighlightData.h; sourceTree = "<group>"; };
|
||||
ED0B1FF32CAAE3FF006E31A4 /* DeepLinkInAppFeatureHighlightData.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DeepLinkInAppFeatureHighlightData.mm; sourceTree = "<group>"; };
|
||||
ED49D7202CED0395004AF27E /* ProductsConfiguration+Core.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "ProductsConfiguration+Core.mm"; sourceTree = "<group>"; };
|
||||
ED49D7232CED03A8004AF27E /* ProductsConfiguration+Core.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ProductsConfiguration+Core.h"; sourceTree = "<group>"; };
|
||||
ED49D7562CEF850F004AF27E /* ProductsConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsConfiguration.swift; sourceTree = "<group>"; };
|
||||
ED49D75E2CEFA8C0004AF27E /* Product+Core.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Product+Core.h"; sourceTree = "<group>"; };
|
||||
ED49D7602CEFA8E1004AF27E /* Product+Core.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "Product+Core.mm"; sourceTree = "<group>"; };
|
||||
ED965B092CD67A470049E39E /* DistanceFormatter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DistanceFormatter.h; sourceTree = "<group>"; };
|
||||
ED965B0A2CD67A470049E39E /* DistanceFormatter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DistanceFormatter.mm; sourceTree = "<group>"; };
|
||||
ED965B112CD67A9B0049E39E /* AltitudeFormatter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AltitudeFormatter.h; sourceTree = "<group>"; };
|
||||
|
@ -310,6 +320,11 @@
|
|||
47F701ED238C86F000D18E95 /* PlacePageButtonsData.h */,
|
||||
47F701F1238C877C00D18E95 /* PlacePageButtonsData+Core.h */,
|
||||
47F701EE238C86F000D18E95 /* PlacePageButtonsData.mm */,
|
||||
ED49D7562CEF850F004AF27E /* ProductsConfiguration.swift */,
|
||||
ED49D7232CED03A8004AF27E /* ProductsConfiguration+Core.h */,
|
||||
ED49D7202CED0395004AF27E /* ProductsConfiguration+Core.mm */,
|
||||
ED49D75E2CEFA8C0004AF27E /* Product+Core.h */,
|
||||
ED49D7602CEFA8E1004AF27E /* Product+Core.mm */,
|
||||
);
|
||||
path = Common;
|
||||
sourceTree = "<group>";
|
||||
|
@ -487,6 +502,7 @@
|
|||
9957FADB237ACB1100855F48 /* DeepLinkSearchData.h in Headers */,
|
||||
479F7056234FB7F200011E2E /* MWMBookmarksManager.h in Headers */,
|
||||
47942D83237CC52E00DEFAE3 /* MWMOpeningHours.h in Headers */,
|
||||
ED49D7242CED03AC004AF27E /* ProductsConfiguration+Core.h in Headers */,
|
||||
4718C4322355FC3C00640DF1 /* MWMNetworkPolicy.h in Headers */,
|
||||
47CA68EC2506F6F100671019 /* MWMTrack+Core.h in Headers */,
|
||||
47F4F1FD23A3D1AC0022FD56 /* MWMMapNodeAttributes+Core.h in Headers */,
|
||||
|
@ -496,6 +512,7 @@
|
|||
47942DA0237D954400DEFAE3 /* PlacePageBookmarkData+Core.h in Headers */,
|
||||
479F704B234F78AB00011E2E /* MWMFrameworkHelper.h in Headers */,
|
||||
47D9019923AC236100D9364C /* MWMMapUpdateInfo+Core.h in Headers */,
|
||||
ED49D75F2CEFA8C0004AF27E /* Product+Core.h in Headers */,
|
||||
47942D6E237CC3E800DEFAE3 /* PlacePagePreviewData+Core.h in Headers */,
|
||||
47942D87237CC55800DEFAE3 /* MWMOpeningHoursCommon.h in Headers */,
|
||||
47942DAB237ED9FE00DEFAE3 /* IOpeningHoursLocalization.h in Headers */,
|
||||
|
@ -615,18 +632,21 @@
|
|||
47D9019623AC22E500D9364C /* MWMMapUpdateInfo.mm in Sources */,
|
||||
47CA68E42506D29000671019 /* MWMBookmarkColor.mm in Sources */,
|
||||
471AB98E23AB925D00F56D49 /* MWMMapSearchResult.mm in Sources */,
|
||||
ED49D7612CEFA8E1004AF27E /* Product+Core.mm in Sources */,
|
||||
47C637D62354AEBE00E12DE0 /* MWMMapOverlayManager.mm in Sources */,
|
||||
475784C32344B422008291A4 /* Framework.cpp in Sources */,
|
||||
4718C4332355FC3C00640DF1 /* MWMNetworkPolicy.mm in Sources */,
|
||||
47CA68E92506F61400671019 /* MWMTrack.mm in Sources */,
|
||||
472602A924092C5B00731135 /* MWMGeoUtil.mm in Sources */,
|
||||
47F701F0238C86F000D18E95 /* PlacePageButtonsData.mm in Sources */,
|
||||
ED49D7222CED0395004AF27E /* ProductsConfiguration+Core.mm in Sources */,
|
||||
9940622123EAC57900493D1A /* ElevationHeightPoint.m in Sources */,
|
||||
ED965B2A2CDA1C440049E39E /* DateTimeFormatter.swift in Sources */,
|
||||
47EEAFF42350CEDB005CF316 /* AppInfo.mm in Sources */,
|
||||
47E8163623B1889C008FD836 /* MWMStorage.mm in Sources */,
|
||||
ED965B0D2CD67A470049E39E /* DistanceFormatter.mm in Sources */,
|
||||
EDC4E3512C5D222D009286A2 /* RecentlyDeletedCategory.mm in Sources */,
|
||||
ED49D75B2CEF8BD2004AF27E /* ProductsConfiguration.swift in Sources */,
|
||||
47CA68DE2502022400671019 /* MWMBookmark.mm in Sources */,
|
||||
9957FAE9237AE5B000855F48 /* Logger.mm in Sources */,
|
||||
ED965B222CD8F5AA0049E39E /* DurationFormatter.mm in Sources */,
|
||||
|
@ -643,7 +663,7 @@
|
|||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = NO;
|
||||
DEFINES_MODULE = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -665,7 +685,7 @@
|
|||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = NO;
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = NO;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
|
|
|
@ -7,6 +7,13 @@
|
|||
|
||||
typedef NS_ENUM(NSUInteger, MWMZoomMode) { MWMZoomModeIn = 0, MWMZoomModeOut };
|
||||
|
||||
typedef NS_ENUM(NSInteger, ProductsPopupCloseReason) {
|
||||
ProductsPopupCloseReasonClose,
|
||||
ProductsPopupCloseReasonSelectProduct,
|
||||
ProductsPopupCloseReasonAlreadyDonated,
|
||||
ProductsPopupCloseReasonRemindLater
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^SearchInDownloaderCompletions)(NSArray<MWMMapSearchResult *> *results, BOOL finished);
|
||||
|
@ -21,8 +28,19 @@ typedef void (^SearchInDownloaderCompletions)(NSArray<MWMMapSearchResult *> *res
|
|||
|
||||
@end
|
||||
|
||||
@class ProductsConfiguration;
|
||||
@class Product;
|
||||
|
||||
@protocol ProductsManager <NSObject>
|
||||
|
||||
+ (nullable ProductsConfiguration *)getProductsConfiguration;
|
||||
+ (void)didCloseProductsPopupWithReason:(ProductsPopupCloseReason)reason;
|
||||
+ (void)didSelectProduct:(Product *)product;
|
||||
|
||||
@end
|
||||
|
||||
NS_SWIFT_NAME(FrameworkHelper)
|
||||
@interface MWMFrameworkHelper : NSObject<TrackRecorder>
|
||||
@interface MWMFrameworkHelper : NSObject<TrackRecorder, ProductsManager>
|
||||
|
||||
+ (void)processFirstLaunch:(BOOL)hasLocation;
|
||||
+ (void)setVisibleViewport:(CGRect)rect scaleFactor:(CGFloat)scale;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#import "MWMFrameworkHelper.h"
|
||||
#import "MWMMapSearchResult+Core.h"
|
||||
#import "ProductsConfiguration+Core.h"
|
||||
#import "Product+Core.h"
|
||||
|
||||
#include "Framework.h"
|
||||
|
||||
|
@ -8,6 +10,19 @@
|
|||
#include "platform/local_country_file_utils.hpp"
|
||||
#include "platform/network_policy_ios.h"
|
||||
|
||||
static Framework::ProductsPopupCloseReason ConvertProductPopupCloseReasonToCore(ProductsPopupCloseReason reason) {
|
||||
switch (reason) {
|
||||
case ProductsPopupCloseReasonClose:
|
||||
return Framework::ProductsPopupCloseReason::Close;
|
||||
case ProductsPopupCloseReasonSelectProduct:
|
||||
return Framework::ProductsPopupCloseReason::SelectProduct;
|
||||
case ProductsPopupCloseReasonAlreadyDonated:
|
||||
return Framework::ProductsPopupCloseReason::AlreadyDonated;
|
||||
case ProductsPopupCloseReasonRemindLater:
|
||||
return Framework::ProductsPopupCloseReason::RemindLater;
|
||||
}
|
||||
}
|
||||
|
||||
@implementation MWMFrameworkHelper
|
||||
|
||||
+ (void)processFirstLaunch:(BOOL)hasLocation {
|
||||
|
@ -196,6 +211,8 @@
|
|||
return GetFramework().GetDrawScale();
|
||||
}
|
||||
|
||||
// MARK: - TrackRecorder
|
||||
|
||||
+ (void)startTrackRecording {
|
||||
GetFramework().StartTrackRecording();
|
||||
}
|
||||
|
@ -216,4 +233,19 @@
|
|||
return GetFramework().IsTrackRecordingEmpty();
|
||||
}
|
||||
|
||||
// MARK: - ProductsManager
|
||||
|
||||
+ (nullable ProductsConfiguration *)getProductsConfiguration {
|
||||
auto const & config = GetFramework().GetProductsConfiguration();
|
||||
return config.has_value() ? [[ProductsConfiguration alloc] init:config.value()] : nil;
|
||||
}
|
||||
|
||||
+ (void)didCloseProductsPopupWithReason:(ProductsPopupCloseReason)reason {
|
||||
GetFramework().DidCloseProductsPopup(ConvertProductPopupCloseReasonToCore(reason));
|
||||
}
|
||||
|
||||
+ (void)didSelectProduct:(Product *)product {
|
||||
GetFramework().DidSelectProduct({product.title.UTF8String, product.link.UTF8String});
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
10
iphone/CoreApi/CoreApi/PlacePageData/Common/Product+Core.h
Normal file
10
iphone/CoreApi/CoreApi/PlacePageData/Common/Product+Core.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <CoreApi/CoreApi-Swift.h>
|
||||
#include <CoreApi/Framework.h>
|
||||
|
||||
#include "platform/products.hpp"
|
||||
|
||||
@interface Product (Core)
|
||||
|
||||
- (nonnull instancetype)init:(products::ProductsConfig::Product const &)product;
|
||||
|
||||
@end
|
11
iphone/CoreApi/CoreApi/PlacePageData/Common/Product+Core.mm
Normal file
11
iphone/CoreApi/CoreApi/PlacePageData/Common/Product+Core.mm
Normal file
|
@ -0,0 +1,11 @@
|
|||
#import "Product+Core.h"
|
||||
|
||||
@implementation Product (Core)
|
||||
|
||||
- (nonnull instancetype)init:(products::ProductsConfig::Product const &)product {
|
||||
self = [self initWithTitle:[NSString stringWithCString:product.GetTitle().c_str() encoding:NSUTF8StringEncoding]
|
||||
link:[NSString stringWithCString:product.GetLink().c_str() encoding:NSUTF8StringEncoding]];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,14 @@
|
|||
#include <CoreApi/CoreApi-Swift.h>
|
||||
#include <CoreApi/Framework.h>
|
||||
|
||||
#include "platform/products.hpp"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ProductsConfiguration (Core)
|
||||
|
||||
- (nonnull instancetype)init:(products::ProductsConfig const &)config;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,15 @@
|
|||
#import "ProductsConfiguration+Core.h"
|
||||
#import "Product+Core.h"
|
||||
|
||||
@implementation ProductsConfiguration (Core)
|
||||
|
||||
- (nonnull instancetype)init:(products::ProductsConfig const &)config {
|
||||
auto const & coreProducts = config.GetProducts();
|
||||
NSMutableArray<Product *> * products = [[NSMutableArray<Product *> alloc] initWithCapacity:coreProducts.size()];
|
||||
for (auto const & product : coreProducts)
|
||||
[products addObject:[[Product alloc] init:product]];
|
||||
self = [self initWithPlacePagePrompt:[NSString stringWithCString:config.GetPlacePagePrompt().c_str() encoding:NSUTF8StringEncoding] products:products];
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,23 @@
|
|||
import Foundation
|
||||
|
||||
@objcMembers
|
||||
public final class Product: NSObject {
|
||||
public let title: String
|
||||
public let link: String
|
||||
|
||||
public init(title: String, link: String) {
|
||||
self.title = title
|
||||
self.link = link
|
||||
}
|
||||
}
|
||||
|
||||
@objcMembers
|
||||
public final class ProductsConfiguration: NSObject {
|
||||
public let placePagePrompt: String
|
||||
public let products: [Product]
|
||||
|
||||
public init(placePagePrompt: String, products: [Product]) {
|
||||
self.placePagePrompt = placePagePrompt
|
||||
self.products = products
|
||||
}
|
||||
}
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "تبرع لبناء أفضل الخرائط معًا!";
|
||||
|
||||
"already_donated" = "تم التبرع";
|
||||
|
||||
"remind_me_later" = "ذكر لاحقاً";
|
||||
|
||||
"support_organic_maps" = "دعم Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "حقوق النشر";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Ən yaxşı xəritələri birlikdə qurmaq üçün ianə edin!";
|
||||
|
||||
"already_donated" = "Artıq ianə edildi";
|
||||
|
||||
"remind_me_later" = "Daha sonra xatırlat";
|
||||
|
||||
"support_organic_maps" = "Organic Maps-i dəstəkləmək";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Müəllif hüququ";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Падтрымайць, каб разам ствараць лепшыя карты!";
|
||||
|
||||
"already_donated" = "Ужо ахвяравана";
|
||||
|
||||
"remind_me_later" = "Нагадаць пазней";
|
||||
|
||||
"support_organic_maps" = "Падтрымаць Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Капірайт";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Дарете, за да създадем заедно най-добрите карти!";
|
||||
|
||||
"already_donated" = "Вече дарено";
|
||||
|
||||
"remind_me_later" = "Напомни по-късно";
|
||||
|
||||
"support_organic_maps" = "Подкрепи Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Авторски права";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Fes una donació per construir els millors mapes junts!";
|
||||
|
||||
"already_donated" = "Ja donat";
|
||||
|
||||
"remind_me_later" = "Recorda més tard";
|
||||
|
||||
"support_organic_maps" = "Donar suport a Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Copyright";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Přispějte, abychom společně vytvořili ty nejlepší mapy!";
|
||||
|
||||
"already_donated" = "Již darováno";
|
||||
|
||||
"remind_me_later" = "Připomeň později";
|
||||
|
||||
"support_organic_maps" = "Podpořit Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Autorská práva";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Donér for at bygge de bedste kort sammen!";
|
||||
|
||||
"already_donated" = "Allerede doneret";
|
||||
|
||||
"remind_me_later" = "Mind mig senere";
|
||||
|
||||
"support_organic_maps" = "Støtte Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Copyright";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Spende, um gemeinsam die besten Karten zu erstellen!";
|
||||
|
||||
"already_donated" = "Bereits gespendet";
|
||||
|
||||
"remind_me_later" = "Später erinnern";
|
||||
|
||||
"support_organic_maps" = "Organic Maps unterstützen";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Copyright";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Κάντε δωρεά για να φτιάξουμε μαζί τους καλύτερους χάρτες!";
|
||||
|
||||
"already_donated" = "Ήδη δωρεά";
|
||||
|
||||
"remind_me_later" = "Υπενθύμισε αργότερα";
|
||||
|
||||
"support_organic_maps" = "Υποστήριξε το Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Πνευματικά δικαιώματα";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Donate to build the best maps together!";
|
||||
|
||||
"already_donated" = "Already donated";
|
||||
|
||||
"remind_me_later" = "Remind later";
|
||||
|
||||
"support_organic_maps" = "Support Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Copyright";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Donate to build the best maps together!";
|
||||
|
||||
"already_donated" = "Already donated";
|
||||
|
||||
"remind_me_later" = "Remind later";
|
||||
|
||||
"support_organic_maps" = "Support Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Copyright";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "¡Dona para construir los mejores mapas juntos!";
|
||||
|
||||
"already_donated" = "Ya donado";
|
||||
|
||||
"remind_me_later" = "Recordar más tarde";
|
||||
|
||||
"support_organic_maps" = "Apoyar Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Derechos de autor";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "¡Haz un donativo para construir juntos los mejores mapas!";
|
||||
|
||||
"already_donated" = "Ya donado";
|
||||
|
||||
"remind_me_later" = "Recordar más tarde";
|
||||
|
||||
"support_organic_maps" = "Apoyar Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Derechos de autor";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Annetage, et ehitada koos parimaid kaarte!";
|
||||
|
||||
"already_donated" = "Juba annetatud";
|
||||
|
||||
"remind_me_later" = "Meenuta hiljem";
|
||||
|
||||
"support_organic_maps" = "Toetada Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Autoriõigused";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Eman dohaintza elkarrekin mapa onenak eraikitzeko!";
|
||||
|
||||
"already_donated" = "Dohaintza jada emana";
|
||||
|
||||
"remind_me_later" = "Gogoratu geroago";
|
||||
|
||||
"support_organic_maps" = "Sustatu Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Egile eskubideak";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "کمک مالی کنید تا بهترین نقشه ها را با هم بسازید!";
|
||||
|
||||
"already_donated" = "قبلاً اهدا شده";
|
||||
|
||||
"remind_me_later" = "بعداً یادآوری کن";
|
||||
|
||||
"support_organic_maps" = "پشتیبانی از Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "حق نشر و کپی رایت";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Lahjoittakaa, jotta voimme rakentaa parhaita karttoja yhdessä!";
|
||||
|
||||
"already_donated" = "Jo lahjoitettu";
|
||||
|
||||
"remind_me_later" = "Muistuta myöhemmin";
|
||||
|
||||
"support_organic_maps" = "Tukea Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Tekijänoikeudet";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Fais un don pour construire ensemble les meilleures cartes !";
|
||||
|
||||
"already_donated" = "Déjà donné";
|
||||
|
||||
"remind_me_later" = "Rappeler plus tard";
|
||||
|
||||
"support_organic_maps" = "Soutenir Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Tous droits réservés";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "תרמו כדי לבנות יחד את המפות הטובות ביותר!";
|
||||
|
||||
"already_donated" = "כבר נתרם";
|
||||
|
||||
"remind_me_later" = "הזכר מאוחר יותר";
|
||||
|
||||
"support_organic_maps" = "לתמוך ב-Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "זכויות יוצרים";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "एक साथ सर्वोत्तम मानचित्र बनाने के लिए दान करें!";
|
||||
|
||||
"already_donated" = "पहले से दान";
|
||||
|
||||
"remind_me_later" = "बाद में याद दिलाना";
|
||||
|
||||
"support_organic_maps" = "Organic Maps का समर्थन करें";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "कॉपीराइट";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Adományozz, hogy együtt építsük a legjobb térképeket!";
|
||||
|
||||
"already_donated" = "Már adományozva";
|
||||
|
||||
"remind_me_later" = "Emlékeztessen később";
|
||||
|
||||
"support_organic_maps" = "Organic Maps támogatása";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Szerzői jog";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Donasi untuk membangun peta terbaik bersama-sama!";
|
||||
|
||||
"already_donated" = "Sudah disumbang";
|
||||
|
||||
"remind_me_later" = "Ingatkan nanti";
|
||||
|
||||
"support_organic_maps" = "Mendukung Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Hak cipta";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Fai una donazione per costruire insieme le migliori mappe!";
|
||||
|
||||
"already_donated" = "Già donato";
|
||||
|
||||
"remind_me_later" = "Ricorda più tardi";
|
||||
|
||||
"support_organic_maps" = "Supportare Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Copyright";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "寄付して最高の地図を一緒に作ろう!";
|
||||
|
||||
"already_donated" = "寄付済み";
|
||||
|
||||
"remind_me_later" = "後でリマインド";
|
||||
|
||||
"support_organic_maps" = "Organic Maps を支援";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "著作権";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "기부하여 최고의 지도를 함께 만들어 보세요!";
|
||||
|
||||
"already_donated" = "기부완료";
|
||||
|
||||
"remind_me_later" = "나중에 알림";
|
||||
|
||||
"support_organic_maps" = "Organic Maps 지원하기";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "저작권";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "एकत्र सर्वोत्तम नकाशे तयार करण्यासाठी देणगी द्या!";
|
||||
|
||||
"already_donated" = "आधीच दान केले";
|
||||
|
||||
"remind_me_later" = "नंतर आठवण करून द्या";
|
||||
|
||||
"support_organic_maps" = "Organic Maps ला समर्थन द्या";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "प्रकाशन अधिकार (कॉपीराईट)";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Doner for å bygge de beste kartene sammen!";
|
||||
|
||||
"already_donated" = "Allerede donert";
|
||||
|
||||
"remind_me_later" = "Påminn senere";
|
||||
|
||||
"support_organic_maps" = "Støtte Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Opphavsrett";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Doneer om samen de beste kaarten te bouwen!";
|
||||
|
||||
"already_donated" = "Reeds gedoneerd";
|
||||
|
||||
"remind_me_later" = "Herinner later";
|
||||
|
||||
"support_organic_maps" = "Ondersteun Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Auteursrechten";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Przekaż darowiznę, aby wspólnie tworzyć najlepsze mapy!";
|
||||
|
||||
"already_donated" = "Już przekazano";
|
||||
|
||||
"remind_me_later" = "Przypomnij później";
|
||||
|
||||
"support_organic_maps" = "Wspierać Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Prawa autorskie";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Doe para criarmos juntos os melhores mapas!";
|
||||
|
||||
"already_donated" = "Já doado";
|
||||
|
||||
"remind_me_later" = "Lembrar mais tarde";
|
||||
|
||||
"support_organic_maps" = "Apoiar Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Direitos autorais";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Faz um donativo para construirmos juntos os melhores mapas!";
|
||||
|
||||
"already_donated" = "Já doado";
|
||||
|
||||
"remind_me_later" = "Lembrar mais tarde";
|
||||
|
||||
"support_organic_maps" = "Apoiar Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Direitos de autor";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Donează pentru a construi împreună cele mai bune hărți!";
|
||||
|
||||
"already_donated" = "Deja donat";
|
||||
|
||||
"remind_me_later" = "Amintește mai târziu";
|
||||
|
||||
"support_organic_maps" = "Susține Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Drepturi de autor";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Поддержать деньгами, чтобы вместе создавать лучшие карты!";
|
||||
|
||||
"already_donated" = "Уже пожертвовано";
|
||||
|
||||
"remind_me_later" = "Напомнить позже";
|
||||
|
||||
"support_organic_maps" = "Поддержать Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Копирайт";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Darujte, aby sme spoločne vytvorili tie najlepšie mapy!";
|
||||
|
||||
"already_donated" = "Už darované";
|
||||
|
||||
"remind_me_later" = "Pripomeň neskôr";
|
||||
|
||||
"support_organic_maps" = "Podporiť Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Autorské práva";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Donera för att bygga de bästa kartorna tillsammans!";
|
||||
|
||||
"already_donated" = "Redan donerat";
|
||||
|
||||
"remind_me_later" = "Påminn senare";
|
||||
|
||||
"support_organic_maps" = "Stödja Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Upphovsrätt";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Changia ili kuunda ramani bora pamoja!";
|
||||
|
||||
"already_donated" = "Tayari kutoa";
|
||||
|
||||
"remind_me_later" = "Kumbusha baadaye";
|
||||
|
||||
"support_organic_maps" = "Kuunga mkono Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Copyright";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "บริจาคเพื่อสร้างแผนที่ที่ดีที่สุดด้วยกัน!";
|
||||
|
||||
"already_donated" = "บริจาคแล้ว";
|
||||
|
||||
"remind_me_later" = "เตือนภายหลัง";
|
||||
|
||||
"support_organic_maps" = "สนับสนุน Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "ลิขสิทธิ์";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "En iyi harita uygulamasını birlikte geliştirmemiz için bağış yapın!";
|
||||
|
||||
"already_donated" = "Zaten bağışlandı";
|
||||
|
||||
"remind_me_later" = "Sonra hatırlat";
|
||||
|
||||
"support_organic_maps" = "Organic Maps’i Desteklemek";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Telif hakkı";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Пожертвуйте, щоб разом створювати найкращі мапи!";
|
||||
|
||||
"already_donated" = "Вже пожертвувано";
|
||||
|
||||
"remind_me_later" = "Нагадати пізніше";
|
||||
|
||||
"support_organic_maps" = "Підтримати Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Копірайт";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "Hãy quyên góp để cùng nhau xây dựng những bản đồ tốt nhất!";
|
||||
|
||||
"already_donated" = "Đã quyên góp";
|
||||
|
||||
"remind_me_later" = "Nhắc sau";
|
||||
|
||||
"support_organic_maps" = "Hỗ trợ Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "Bản quyền";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "捐助,以共同打造最好的地图!";
|
||||
|
||||
"already_donated" = "已捐赠";
|
||||
|
||||
"remind_me_later" = "稍后提醒";
|
||||
|
||||
"support_organic_maps" = "支持 Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "版权";
|
||||
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
/* Tex label above the Donate button */
|
||||
"donate_description" = "捐助,以共同打造最好的地圖!";
|
||||
|
||||
"already_donated" = "已捐贈";
|
||||
|
||||
"remind_me_later" = "稍後提醒";
|
||||
|
||||
"support_organic_maps" = "支持 Organic Maps";
|
||||
|
||||
/* Button in the main Help dialog */
|
||||
"copyright" = "版權";
|
||||
|
||||
|
|
|
@ -477,6 +477,9 @@
|
|||
ED1ADA332BC6B1B40029209F /* CarPlayServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1ADA322BC6B1B40029209F /* CarPlayServiceTests.swift */; };
|
||||
ED3EAC202B03C88100220A4A /* BottomTabBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3EAC1F2B03C88100220A4A /* BottomTabBarButton.swift */; };
|
||||
ED43B8BD2C12063500D07BAA /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED43B8BC2C12063500D07BAA /* DocumentPicker.swift */; };
|
||||
ED4DC7792CAEDECC0029B338 /* ProductsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4DC7742CAEDECC0029B338 /* ProductsViewController.swift */; };
|
||||
ED4DC7782CAEDECC0029B338 /* ProductButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4DC7732CAEDECC0029B338 /* ProductButton.swift */; };
|
||||
ED4DC7772CAEDECC0029B338 /* ProductsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4DC7752CAEDECC0029B338 /* ProductsViewModel.swift */; };
|
||||
ED63CEB92BDF8F9D006155C4 /* SettingsTableViewiCloudSwitchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED63CEB62BDF8F9C006155C4 /* SettingsTableViewiCloudSwitchCell.swift */; };
|
||||
ED77556E2C2C490B0051E656 /* UIAlertController+openInAppActionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED77556D2C2C490B0051E656 /* UIAlertController+openInAppActionSheet.swift */; };
|
||||
ED79A5AB2BD7AA9C00952D1F /* LoadingOverlayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED79A5AA2BD7AA9C00952D1F /* LoadingOverlayViewController.swift */; };
|
||||
|
@ -1405,6 +1408,9 @@
|
|||
ED43B8BC2C12063500D07BAA /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = "<group>"; };
|
||||
ED48BBB817C2B1E2003E7E92 /* CircleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircleView.h; sourceTree = "<group>"; };
|
||||
ED48BBB917C2B1E2003E7E92 /* CircleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CircleView.m; sourceTree = "<group>"; };
|
||||
ED4DC7732CAEDECC0029B338 /* ProductButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductButton.swift; sourceTree = "<group>"; };
|
||||
ED4DC7742CAEDECC0029B338 /* ProductsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsViewController.swift; sourceTree = "<group>"; };
|
||||
ED4DC7752CAEDECC0029B338 /* ProductsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductsViewModel.swift; sourceTree = "<group>"; };
|
||||
ED63CEB62BDF8F9C006155C4 /* SettingsTableViewiCloudSwitchCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsTableViewiCloudSwitchCell.swift; sourceTree = "<group>"; };
|
||||
ED77556D2C2C490B0051E656 /* UIAlertController+openInAppActionSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+openInAppActionSheet.swift"; sourceTree = "<group>"; };
|
||||
ED79A5AA2BD7AA9C00952D1F /* LoadingOverlayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingOverlayViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -2943,6 +2949,7 @@
|
|||
993DF0C223F6BD0600AC231A /* ElevationDetails */,
|
||||
99DEF9D523E420D2006BFD21 /* ElevationProfile */,
|
||||
EDE8EAE32C2DB74A002777F5 /* OpenInAppActionSheet */,
|
||||
ED4DC7762CAEDECC0029B338 /* Products */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3114,6 +3121,16 @@
|
|||
path = DocumentPicker;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
ED4DC7762CAEDECC0029B338 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED4DC7732CAEDECC0029B338 /* ProductButton.swift */,
|
||||
ED4DC7742CAEDECC0029B338 /* ProductsViewController.swift */,
|
||||
ED4DC7752CAEDECC0029B338 /* ProductsViewModel.swift */,
|
||||
);
|
||||
path = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
ED79A5A92BD7AA7500952D1F /* LoadingOverlay */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -4468,6 +4485,9 @@
|
|||
34BF0CC71C31304A00D097EB /* MWMAuthorizationCommon.mm in Sources */,
|
||||
34AB664D1FC5AA330078E451 /* RouteManagerFooterView.swift in Sources */,
|
||||
6741A9E01BF340DE002C974C /* MWMDownloaderDialogHeader.mm in Sources */,
|
||||
ED4DC7772CAEDECC0029B338 /* ProductsViewModel.swift in Sources */,
|
||||
ED4DC7782CAEDECC0029B338 /* ProductButton.swift in Sources */,
|
||||
ED4DC7792CAEDECC0029B338 /* ProductsViewController.swift in Sources */,
|
||||
CDCA2748223FD24600167D87 /* MWMCarPlaySearchResultObject.mm in Sources */,
|
||||
475ED78824C7D0F30063ADC7 /* ValueStepperView.swift in Sources */,
|
||||
3454D7E01E07F045004AF2AD /* UITextField+RuntimeAttributes.m in Sources */,
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
final class ProductButton: UIButton {
|
||||
|
||||
private var action: () -> Void
|
||||
|
||||
init(title: String, action: @escaping () -> Void) {
|
||||
self.action = action
|
||||
super.init(frame: .zero)
|
||||
self.setup(title: title, action: action)
|
||||
self.layout()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func setup(title: String, action: @escaping () -> Void) {
|
||||
setStyleAndApply("BlueBackground")
|
||||
setTitle(title, for: .normal)
|
||||
setTitleColor(.white, for: .normal)
|
||||
titleLabel?.font = UIFont.regular14()
|
||||
titleLabel?.allowsDefaultTighteningForTruncation = true
|
||||
titleLabel?.adjustsFontSizeToFitWidth = true
|
||||
titleLabel?.minimumScaleFactor = 0.5
|
||||
layer.setCorner(radius: 5.0)
|
||||
layer.masksToBounds = true
|
||||
addTarget(self, action: #selector(buttonDidTap), for: .touchUpInside)
|
||||
}
|
||||
|
||||
private func layout() {
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
heightAnchor.constraint(equalToConstant: 30.0).isActive = true
|
||||
}
|
||||
|
||||
@objc private func buttonDidTap() {
|
||||
action()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
final class ProductsViewController: UIViewController {
|
||||
|
||||
private enum Constants {
|
||||
static let spacing: CGFloat = 10
|
||||
static let titleLeadingPadding: CGFloat = 12
|
||||
static let titleTrailingPadding: CGFloat = 10
|
||||
static let descriptionTopPadding: CGFloat = 10
|
||||
static let closeButtonSize: CGFloat = 24
|
||||
static let closeButtonTrailingPadding: CGFloat = -12
|
||||
static let closeButtonTopPadding: CGFloat = 12
|
||||
static let stackViewTopPadding: CGFloat = 12
|
||||
static let subtitleButtonTopPadding: CGFloat = 4
|
||||
static let subtitleButtonBottomPadding: CGFloat = -4
|
||||
}
|
||||
|
||||
private let viewModel: ProductsViewModel
|
||||
private let titleLabel = UILabel()
|
||||
private let descriptionLabel = UILabel()
|
||||
private let closeButton = UIButton(type: .system)
|
||||
private let stackView = UIStackView()
|
||||
private let leadingSubtitleButton = UIButton(type: .system)
|
||||
private let trailingSubtitleButton = UIButton(type: .system)
|
||||
|
||||
init(viewModel: ProductsViewModel) {
|
||||
self.viewModel = viewModel
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupViews()
|
||||
layout()
|
||||
}
|
||||
|
||||
private func setupViews() {
|
||||
view.setStyleAndApply("Background")
|
||||
setupTitleLabel()
|
||||
setupDescriptionLabel()
|
||||
setupCloseButton()
|
||||
setupProductsStackView()
|
||||
setupSubtitleButtons()
|
||||
}
|
||||
|
||||
private func setupTitleLabel() {
|
||||
titleLabel.text = viewModel.title
|
||||
titleLabel.font = UIFont.semibold16()
|
||||
titleLabel.numberOfLines = 1
|
||||
titleLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
private func setupDescriptionLabel() {
|
||||
descriptionLabel.text = viewModel.description
|
||||
descriptionLabel.font = UIFont.regular14()
|
||||
descriptionLabel.numberOfLines = 0
|
||||
descriptionLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
|
||||
private func setupCloseButton() {
|
||||
closeButton.setStyleAndApply("MWMGray")
|
||||
closeButton.setImage(UIImage(resource: .icSearchClear), for: .normal)
|
||||
closeButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
closeButton.addTarget(self, action: #selector(closeButtonDidTap), for: .touchUpInside)
|
||||
}
|
||||
|
||||
private func setupProductsStackView() {
|
||||
stackView.axis = .horizontal
|
||||
stackView.alignment = .fill
|
||||
stackView.distribution = .fillEqually
|
||||
stackView.spacing = Constants.spacing
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
viewModel.products.forEach { product in
|
||||
let button = ProductButton(title: product.title) { [weak self] in
|
||||
self?.productButtonDidTap(product)
|
||||
}
|
||||
stackView.addArrangedSubview(button)
|
||||
}
|
||||
}
|
||||
|
||||
private func setupSubtitleButtons() {
|
||||
leadingSubtitleButton.setTitle(viewModel.leadingSubtitle, for: .normal)
|
||||
leadingSubtitleButton.backgroundColor = .clear
|
||||
leadingSubtitleButton.setTitleColor(.linkBlue(), for: .normal)
|
||||
leadingSubtitleButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
leadingSubtitleButton.addTarget(self, action: #selector(leadingSubtitleButtonDidTap), for: .touchUpInside)
|
||||
|
||||
trailingSubtitleButton.setTitle(viewModel.trailingSubtitle, for: .normal)
|
||||
trailingSubtitleButton.backgroundColor = .clear
|
||||
trailingSubtitleButton.setTitleColor(.linkBlue(), for: .normal)
|
||||
trailingSubtitleButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
trailingSubtitleButton.addTarget(self, action: #selector(trailingSubtitleButtonDidTap), for: .touchUpInside)
|
||||
}
|
||||
|
||||
private func layout() {
|
||||
view.addSubview(titleLabel)
|
||||
view.addSubview(descriptionLabel)
|
||||
view.addSubview(closeButton)
|
||||
view.addSubview(stackView)
|
||||
view.addSubview(leadingSubtitleButton)
|
||||
view.addSubview(trailingSubtitleButton)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
titleLabel.topAnchor.constraint(equalTo: closeButton.topAnchor),
|
||||
titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Constants.titleLeadingPadding),
|
||||
titleLabel.trailingAnchor.constraint(equalTo: closeButton.leadingAnchor),
|
||||
|
||||
descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: Constants.descriptionTopPadding),
|
||||
descriptionLabel.leadingAnchor.constraint(equalTo: titleLabel.leadingAnchor),
|
||||
descriptionLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Constants.titleTrailingPadding),
|
||||
|
||||
closeButton.widthAnchor.constraint(equalToConstant: Constants.closeButtonSize),
|
||||
closeButton.heightAnchor.constraint(equalToConstant: Constants.closeButtonSize),
|
||||
closeButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: Constants.closeButtonTrailingPadding),
|
||||
closeButton.topAnchor.constraint(equalTo: view.topAnchor, constant: Constants.closeButtonTopPadding),
|
||||
|
||||
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Constants.titleLeadingPadding),
|
||||
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Constants.titleLeadingPadding),
|
||||
stackView.topAnchor.constraint(equalTo: descriptionLabel.bottomAnchor, constant: Constants.stackViewTopPadding),
|
||||
|
||||
leadingSubtitleButton.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: Constants.subtitleButtonTopPadding),
|
||||
leadingSubtitleButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Constants.titleLeadingPadding),
|
||||
leadingSubtitleButton.trailingAnchor.constraint(equalTo: view.centerXAnchor),
|
||||
leadingSubtitleButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: Constants.subtitleButtonBottomPadding),
|
||||
|
||||
trailingSubtitleButton.topAnchor.constraint(equalTo: leadingSubtitleButton.topAnchor, constant: Constants.subtitleButtonTopPadding),
|
||||
trailingSubtitleButton.leadingAnchor.constraint(equalTo: view.centerXAnchor),
|
||||
trailingSubtitleButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Constants.titleLeadingPadding),
|
||||
trailingSubtitleButton.bottomAnchor.constraint(equalTo: leadingSubtitleButton.bottomAnchor)
|
||||
])
|
||||
}
|
||||
|
||||
@objc private func closeButtonDidTap() {
|
||||
viewModel.didClose(reason: .close)
|
||||
hide()
|
||||
}
|
||||
|
||||
private func productButtonDidTap(_ product: Product) {
|
||||
viewModel.didSelectProduct(product)
|
||||
viewModel.didClose(reason: .selectProduct)
|
||||
hide()
|
||||
}
|
||||
|
||||
@objc private func leadingSubtitleButtonDidTap() {
|
||||
viewModel.didClose(reason: .alreadyDonated)
|
||||
hide()
|
||||
}
|
||||
|
||||
@objc private func trailingSubtitleButtonDidTap() {
|
||||
viewModel.didClose(reason: .remindLater)
|
||||
hide()
|
||||
}
|
||||
|
||||
func hide() {
|
||||
UIView.transition(with: view, duration: kDefaultAnimationDuration / 2, options: .transitionCrossDissolve) {
|
||||
self.view.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
struct ProductsViewModel {
|
||||
private let productsManager: ProductsManager.Type
|
||||
|
||||
let title: String = L("support_organic_maps")
|
||||
let description: String
|
||||
let leadingSubtitle: String = L("already_donated")
|
||||
let trailingSubtitle: String = L("remind_me_later")
|
||||
let products: [Product]
|
||||
|
||||
init(manager: ProductsManager.Type, configuration: ProductsConfiguration) {
|
||||
self.productsManager = manager
|
||||
self.description = configuration.placePagePrompt
|
||||
self.products = configuration.products
|
||||
}
|
||||
|
||||
func didSelectProduct(_ product: Product) {
|
||||
UIViewController.topViewController().openUrl(product.link, externally: true)
|
||||
productsManager.didSelect(product)
|
||||
}
|
||||
|
||||
func didClose(reason: ProductsPopupCloseReason) {
|
||||
productsManager.didCloseProductsPopup(with: reason)
|
||||
}
|
||||
}
|
|
@ -57,6 +57,13 @@ class PlacePageCommonLayout: NSObject, IPlacePageLayout {
|
|||
return vc
|
||||
} ()
|
||||
|
||||
private func productsViewController() -> ProductsViewController? {
|
||||
let productsManager = FrameworkHelper.self
|
||||
guard let configuration = productsManager.getProductsConfiguration() else { return nil }
|
||||
let viewModel = ProductsViewModel(manager: productsManager, configuration: configuration)
|
||||
return ProductsViewController(viewModel: viewModel)
|
||||
}
|
||||
|
||||
lazy var buttonsViewController: PlacePageButtonsViewController = {
|
||||
let vc = storyboard.instantiateViewController(ofType: PlacePageButtonsViewController.self)
|
||||
vc.buttonsData = placePageData.buttonsData!
|
||||
|
@ -85,6 +92,7 @@ class PlacePageCommonLayout: NSObject, IPlacePageLayout {
|
|||
|
||||
private func configureViewControllers() -> [UIViewController] {
|
||||
var viewControllers = [UIViewController]()
|
||||
|
||||
viewControllers.append(wikiDescriptionViewController)
|
||||
if let wikiDescriptionHtml = placePageData.wikiDescriptionHtml {
|
||||
wikiDescriptionViewController.descriptionHtml = wikiDescriptionHtml
|
||||
|
@ -103,6 +111,10 @@ class PlacePageCommonLayout: NSObject, IPlacePageLayout {
|
|||
viewControllers.append(infoViewController)
|
||||
}
|
||||
|
||||
if let productsViewController = productsViewController() {
|
||||
viewControllers.append(productsViewController)
|
||||
}
|
||||
|
||||
if placePageData.buttonsData != nil {
|
||||
viewControllers.append(buttonsViewController)
|
||||
}
|
||||
|
|
Reference in a new issue