[ios] Add a products section to the place page #8638

Merged
root merged 3 commits from ios/add-dontation-section-to-pp into master 2024-11-26 13:38:44 +00:00
56 changed files with 791 additions and 3 deletions

View file

@ -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
Review
    de = Bereits gespendet
```suggestion de = Bereits gespendet ```
el = Ήδη δωρεά
es = Ya donado
et = Juba annetatud
eu = Dohaintza jada emana
andergd commented 2024-11-25 18:55:09 +00:00 (Migrated from github.com)
Review

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
soshial commented 2024-11-25 20:13:35 +00:00 (Migrated from github.com)
Review

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 = Уже пожертвовано
vng commented 2024-11-25 17:49:24 +00:00 (Migrated from github.com)
Review

Уже задонатил?

Уже задонатил?
Review

не подходит для женщин, надо нейтрально
"Уже пожертвовано"
поэтому нормально

не подходит для женщин, надо нейтрально "Уже пожертвовано" поэтому нормально
Review

Пожертвовано - это про церковь.

Пожертвовано - это про церковь.
soshial commented 2024-11-25 20:10:32 +00:00 (Migrated from github.com)
Review

А можно нормальным русским языком без вот этих "донатов"? 🍩

"Пожертвование" и "благотворительность" — абсолютно нормальные слова и не обязательно сразу церковь.

А можно нормальным русским языком без вот этих "донатов"? 🍩 "Пожертвование" и "благотворительность" — абсолютно нормальные слова и не обязательно сразу церковь.
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
Review
    de = Später erinnern
```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
andergd commented 2024-11-25 18:56:05 +00:00 (Migrated from github.com)
Review

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
jimcarst commented 2024-11-25 17:24:50 +00:00 (Migrated from github.com)
Review
    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 Mapsi 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

View file

@ -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 = (

View file

@ -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;

View file

@ -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

View 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

View 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

View file

@ -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

View file

@ -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

View file

@ -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
}
}

View file

@ -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" = "حقوق النشر";

View file

@ -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";

View file

@ -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" = "Капірайт";

View file

@ -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" = "Авторски права";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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" = "Πνευματικά δικαιώματα";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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" = "حق نشر و کپی رایت";

View file

@ -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";

View file

@ -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";

View file

@ -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" = "זכויות יוצרים";

View file

@ -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" = "कॉपीराइट";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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" = "著作権";

View file

@ -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" = "저작권";

View file

@ -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" = "प्रकाशन अधिकार (कॉपीराईट)";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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" = "Копирайт";

View file

@ -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";

View file

@ -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";

View file

@ -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";

View file

@ -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" = "ลิขสิทธิ์";

View file

@ -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 Mapsi Desteklemek";
/* Button in the main Help dialog */
"copyright" = "Telif hakkı";

View file

@ -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" = "Копірайт";

View file

@ -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";

View file

@ -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" = "版权";

View file

@ -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" = "版權";

View file

@ -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 */,

View file

@ -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()
}
}

View file

@ -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
}
}
}

View file

@ -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)
}
}

View file

@ -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)
}