1
This commit is contained in:
@@ -2966,7 +2966,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.loveKey.nyx;
|
PRODUCT_BUNDLE_IDENTIFIER = com.loveKey.nyx;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
@@ -3017,7 +3017,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.loveKey.nyx;
|
PRODUCT_BUNDLE_IDENTIFIER = com.loveKey.nyx;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
|||||||
|
|
||||||
@interface AppDelegate () <KBAppUpdateViewDelegate>
|
@interface AppDelegate () <KBAppUpdateViewDelegate>
|
||||||
@property (nonatomic, strong) LSTPopView *appUpdatePopView;
|
@property (nonatomic, strong) LSTPopView *appUpdatePopView;
|
||||||
@property (nonatomic, copy) NSString *appUpdateURLString;
|
@property (nonatomic, strong) KBAppUpdateInfo *appUpdateInfo;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
@@ -89,53 +89,24 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
|||||||
|
|
||||||
- (void)kb_requestAppUpdateAndPresentIfNeeded {
|
- (void)kb_requestAppUpdateAndPresentIfNeeded {
|
||||||
__weak typeof(self) weakSelf = self;
|
__weak typeof(self) weakSelf = self;
|
||||||
[[KBLoginVM shared] checkAppUpdateWithCompletion:^(NSDictionary * _Nullable data, NSError * _Nullable error) {
|
[[KBLoginVM shared] checkAppUpdateWithCompletion:^(KBAppUpdateInfo * _Nullable info, NSError * _Nullable error) {
|
||||||
if (error) { return; }
|
if (error) { return; }
|
||||||
if (![data isKindOfClass:NSDictionary.class]) { return; }
|
if (!info.needUpdate) { return; }
|
||||||
NSDictionary *payload = data[@"data"];
|
|
||||||
if (![payload isKindOfClass:NSDictionary.class]) {
|
|
||||||
payload = (NSDictionary *)data;
|
|
||||||
}
|
|
||||||
if (![payload isKindOfClass:NSDictionary.class]) { return; }
|
|
||||||
if (![weakSelf kb_shouldPresentAppUpdateWithData:payload]) { return; }
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[weakSelf kb_presentAppUpdateWithData:payload];
|
[weakSelf kb_presentAppUpdateWithInfo:info];
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)kb_presentAppUpdateWithData:(NSDictionary *)data {
|
- (void)kb_presentAppUpdateWithInfo:(KBAppUpdateInfo *)info {
|
||||||
if (self.appUpdatePopView) { return; }
|
if (self.appUpdatePopView) { return; }
|
||||||
|
self.appUpdateInfo = info;
|
||||||
CGFloat width = KBFit(323.0);
|
CGFloat width = KBFit(323.0);
|
||||||
CGFloat height = KBFit(390.0);
|
CGFloat height = KBFit(390.0);
|
||||||
KBAppUpdateView *view = [[KBAppUpdateView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
|
KBAppUpdateView *view = [[KBAppUpdateView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
|
||||||
view.backgroundImageName = @"app_update_bg";
|
view.backgroundImageName = @"app_update_bg";
|
||||||
view.delegate = self;
|
view.delegate = self;
|
||||||
NSString *title = [self kb_stringForKeys:@[@"title", @"updateTitle", @"headline", @"appTitle"] inDictionary:data];
|
view.updateInfo = info;
|
||||||
if (title.length > 0) {
|
|
||||||
view.titleText = title;
|
|
||||||
}
|
|
||||||
NSString *versionName = [self kb_stringForKeys:@[@"versionName", @"latestVersionName", @"newVersionName", @"version", @"latestVersion"] inDictionary:data];
|
|
||||||
if (versionName.length > 0) {
|
|
||||||
if (![versionName hasPrefix:@"V"] && ![versionName hasPrefix:@"v"]) {
|
|
||||||
versionName = [NSString stringWithFormat:@"V%@", versionName];
|
|
||||||
}
|
|
||||||
view.versionText = versionName;
|
|
||||||
}
|
|
||||||
NSString *contentTitle = [self kb_stringForKeys:@[@"contentTitle", @"updateContentTitle", @"descTitle", @"updateDescTitle"] inDictionary:data];
|
|
||||||
if (contentTitle.length > 0) {
|
|
||||||
view.contentTitleText = contentTitle;
|
|
||||||
}
|
|
||||||
id contentObj = [self kb_objectForKeys:@[@"contentItems", @"updateContent", @"updateDesc", @"description", @"desc", @"content"] inDictionary:data];
|
|
||||||
NSArray<NSString *> *items = [self kb_contentItemsFromObject:contentObj];
|
|
||||||
if (items.count > 0) {
|
|
||||||
view.contentItems = items;
|
|
||||||
}
|
|
||||||
NSString *buttonTitle = [self kb_stringForKeys:@[@"upgradeButtonTitle", @"upgradeButtonText", @"buttonText", @"buttonTitle"] inDictionary:data];
|
|
||||||
if (buttonTitle.length > 0) {
|
|
||||||
view.upgradeButtonTitle = buttonTitle;
|
|
||||||
}
|
|
||||||
self.appUpdateURLString = [self kb_stringForKeys:@[@"downloadUrl", @"downloadURL", @"url", @"appStoreUrl", @"appStoreURL", @"installUrl", @"upgradeUrl"] inDictionary:data];
|
|
||||||
|
|
||||||
LSTPopView *pop = [LSTPopView initWithCustomView:view
|
LSTPopView *pop = [LSTPopView initWithCustomView:view
|
||||||
parentView:nil
|
parentView:nil
|
||||||
@@ -149,143 +120,10 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
|||||||
[pop pop];
|
[pop pop];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)kb_shouldPresentAppUpdateWithData:(NSDictionary *)data {
|
|
||||||
NSArray<NSString *> *flagKeys = @[@"needUpdate", @"hasUpdate", @"shouldUpdate", @"needUpgrade", @"hasUpgrade", @"update", @"isUpdate"];
|
|
||||||
for (NSString *key in flagKeys) {
|
|
||||||
id obj = data[key];
|
|
||||||
if (obj && ![obj isKindOfClass:NSNull.class] &&
|
|
||||||
([obj isKindOfClass:NSNumber.class] || [obj isKindOfClass:NSString.class])) {
|
|
||||||
return [self kb_boolValueFromObject:obj];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NSArray<NSString *> *typeKeys = @[@"updateType", @"upgradeType", @"updateMode"];
|
|
||||||
for (NSString *key in typeKeys) {
|
|
||||||
id obj = data[key];
|
|
||||||
if (obj && ![obj isKindOfClass:NSNull.class] &&
|
|
||||||
([obj isKindOfClass:NSNumber.class] || [obj isKindOfClass:NSString.class])) {
|
|
||||||
NSInteger typeValue = [self kb_integerValueFromObject:obj];
|
|
||||||
return typeValue > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NSInteger localCode = [self kb_localVersionCode];
|
|
||||||
NSArray<NSString *> *codeKeys = @[@"versionCode", @"latestVersionCode", @"newVersionCode", @"latestCode", @"buildNumber"];
|
|
||||||
for (NSString *key in codeKeys) {
|
|
||||||
id obj = data[key];
|
|
||||||
if (obj && ![obj isKindOfClass:NSNull.class]) {
|
|
||||||
NSInteger remoteCode = [self kb_versionCodeFromObject:obj];
|
|
||||||
if (remoteCode > 0 && localCode > 0) {
|
|
||||||
return remoteCode > localCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (nullable id)kb_objectForKeys:(NSArray<NSString *> *)keys inDictionary:(NSDictionary *)dict {
|
|
||||||
for (NSString *key in keys) {
|
|
||||||
id obj = dict[key];
|
|
||||||
if (obj && ![obj isKindOfClass:NSNull.class]) {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (nullable NSString *)kb_stringForKeys:(NSArray<NSString *> *)keys inDictionary:(NSDictionary *)dict {
|
|
||||||
id obj = [self kb_objectForKeys:keys inDictionary:dict];
|
|
||||||
return [self kb_stringFromObject:obj];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (nullable NSString *)kb_stringFromObject:(id)obj {
|
|
||||||
if ([obj isKindOfClass:NSString.class]) { return (NSString *)obj; }
|
|
||||||
if ([obj respondsToSelector:@selector(stringValue)]) { return [obj stringValue]; }
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)kb_boolValueFromObject:(id)obj {
|
|
||||||
if ([obj isKindOfClass:NSNumber.class]) { return ((NSNumber *)obj).boolValue; }
|
|
||||||
if ([obj isKindOfClass:NSString.class]) {
|
|
||||||
NSString *lower = [(NSString *)obj lowercaseString];
|
|
||||||
if ([lower isEqualToString:@"true"] || [lower isEqualToString:@"yes"]) { return YES; }
|
|
||||||
if ([lower isEqualToString:@"false"] || [lower isEqualToString:@"no"]) { return NO; }
|
|
||||||
return lower.integerValue != 0;
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSInteger)kb_integerValueFromObject:(id)obj {
|
|
||||||
if ([obj respondsToSelector:@selector(integerValue)]) { return [obj integerValue]; }
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSInteger)kb_versionCodeFromObject:(id)obj {
|
|
||||||
if ([obj isKindOfClass:NSString.class]) {
|
|
||||||
NSString *digits = [self kb_digitsOnlyStringFromString:obj];
|
|
||||||
if (digits.length > 0) { return digits.longLongValue; }
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ([obj respondsToSelector:@selector(longLongValue)]) {
|
|
||||||
return (NSInteger)[obj longLongValue];
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSArray<NSString *> *)kb_contentItemsFromObject:(id)obj {
|
|
||||||
if ([obj isKindOfClass:NSArray.class]) {
|
|
||||||
NSMutableArray<NSString *> *items = [NSMutableArray array];
|
|
||||||
for (id item in (NSArray *)obj) {
|
|
||||||
NSString *text = [self kb_stringFromObject:item];
|
|
||||||
if (text.length > 0) {
|
|
||||||
[items addObject:text];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
if ([obj isKindOfClass:NSString.class]) {
|
|
||||||
NSString *text = [(NSString *)obj stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
||||||
if (text.length == 0) { return @[]; }
|
|
||||||
NSCharacterSet *splitSet = [NSCharacterSet characterSetWithCharactersInString:@"\n;"];
|
|
||||||
NSArray<NSString *> *parts = [text componentsSeparatedByCharactersInSet:splitSet];
|
|
||||||
NSMutableArray<NSString *> *items = [NSMutableArray array];
|
|
||||||
for (NSString *part in parts) {
|
|
||||||
NSString *trimmed = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
||||||
if (trimmed.length > 0) {
|
|
||||||
[items addObject:trimmed];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return items.count > 0 ? items : @[text];
|
|
||||||
}
|
|
||||||
return @[];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSInteger)kb_localVersionCode {
|
|
||||||
NSString *buildNumber = [self kb_stringFromObject:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]];
|
|
||||||
NSString *shortVersion = [self kb_stringFromObject:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]];
|
|
||||||
NSString *digits = [self kb_digitsOnlyStringFromString:buildNumber];
|
|
||||||
if (digits.length == 0) {
|
|
||||||
digits = [self kb_digitsOnlyStringFromString:shortVersion];
|
|
||||||
}
|
|
||||||
if (digits.length == 0) { return 0; }
|
|
||||||
return digits.longLongValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (nullable NSString *)kb_digitsOnlyStringFromString:(nullable NSString *)string {
|
|
||||||
if (![string isKindOfClass:NSString.class] || string.length == 0) { return nil; }
|
|
||||||
NSCharacterSet *set = [NSCharacterSet decimalDigitCharacterSet];
|
|
||||||
NSMutableString *digits = [NSMutableString string];
|
|
||||||
for (NSUInteger i = 0; i < string.length; i++) {
|
|
||||||
unichar c = [string characterAtIndex:i];
|
|
||||||
if ([set characterIsMember:c]) {
|
|
||||||
[digits appendFormat:@"%C", c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return digits;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - KBAppUpdateViewDelegate
|
#pragma mark - KBAppUpdateViewDelegate
|
||||||
|
|
||||||
- (void)appUpdateViewDidTapUpgrade:(KBAppUpdateView *)view {
|
- (void)appUpdateViewDidTapUpgrade:(KBAppUpdateView *)view {
|
||||||
NSString *urlString = self.appUpdateURLString;
|
NSString *urlString = self.appUpdateInfo.downloadUrl;
|
||||||
if (urlString.length > 0) {
|
if (urlString.length > 0) {
|
||||||
NSURL *url = [NSURL URLWithString:urlString];
|
NSURL *url = [NSURL URLWithString:urlString];
|
||||||
if (url) {
|
if (url) {
|
||||||
@@ -299,9 +137,15 @@ static NSTimeInterval const kKBSubscriptionPrefillTTL = 10 * 60.0;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// [self.appUpdatePopView dismiss];
|
||||||
|
// self.appUpdatePopView = nil;
|
||||||
|
// self.appUpdateInfo = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)appUpdateViewDidTapCancel:(KBAppUpdateView *)view {
|
||||||
[self.appUpdatePopView dismiss];
|
[self.appUpdatePopView dismiss];
|
||||||
self.appUpdatePopView = nil;
|
self.appUpdatePopView = nil;
|
||||||
self.appUpdateURLString = nil;
|
self.appUpdateInfo = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationDidBecomeActive:(UIApplication *)application{
|
- (void)applicationDidBecomeActive:(UIApplication *)application{
|
||||||
|
|||||||
@@ -8,15 +8,18 @@
|
|||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@class KBAppUpdateView;
|
@class KBAppUpdateView;
|
||||||
|
@class KBAppUpdateInfo;
|
||||||
|
|
||||||
@protocol KBAppUpdateViewDelegate <NSObject>
|
@protocol KBAppUpdateViewDelegate <NSObject>
|
||||||
@optional
|
@optional
|
||||||
- (void)appUpdateViewDidTapUpgrade:(KBAppUpdateView *)view;
|
- (void)appUpdateViewDidTapUpgrade:(KBAppUpdateView *)view;
|
||||||
|
- (void)appUpdateViewDidTapCancel:(KBAppUpdateView *)view;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface KBAppUpdateView : UIView
|
@interface KBAppUpdateView : UIView
|
||||||
|
|
||||||
@property (nonatomic, weak) id<KBAppUpdateViewDelegate> delegate;
|
@property (nonatomic, weak) id<KBAppUpdateViewDelegate> delegate;
|
||||||
|
@property (nonatomic, strong, nullable) KBAppUpdateInfo *updateInfo;
|
||||||
|
|
||||||
@property (nonatomic, copy) NSString *backgroundImageName;
|
@property (nonatomic, copy) NSString *backgroundImageName;
|
||||||
@property (nonatomic, copy) NSString *titleText;
|
@property (nonatomic, copy) NSString *titleText;
|
||||||
@@ -24,6 +27,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@property (nonatomic, copy) NSString *contentTitleText;
|
@property (nonatomic, copy) NSString *contentTitleText;
|
||||||
@property (nonatomic, copy) NSArray<NSString *> *contentItems;
|
@property (nonatomic, copy) NSArray<NSString *> *contentItems;
|
||||||
@property (nonatomic, copy) NSString *upgradeButtonTitle;
|
@property (nonatomic, copy) NSString *upgradeButtonTitle;
|
||||||
|
@property (nonatomic, copy) NSString *cancelButtonTitle;
|
||||||
|
@property (nonatomic, assign) BOOL showsCancelButton;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "KBAppUpdateView.h"
|
#import "KBAppUpdateView.h"
|
||||||
|
#import "KBLoginVM.h"
|
||||||
|
|
||||||
@interface KBAppUpdateView ()
|
@interface KBAppUpdateView ()
|
||||||
@property (nonatomic, strong) UIImageView *backgroundImageView;
|
@property (nonatomic, strong) UIImageView *backgroundImageView;
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
@property (nonatomic, strong) UILabel *contentTitleLabel;
|
@property (nonatomic, strong) UILabel *contentTitleLabel;
|
||||||
@property (nonatomic, strong) UILabel *contentLabel;
|
@property (nonatomic, strong) UILabel *contentLabel;
|
||||||
@property (nonatomic, strong) UIButton *upgradeButton;
|
@property (nonatomic, strong) UIButton *upgradeButton;
|
||||||
|
@property (nonatomic, strong) UIButton *cancelButton;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation KBAppUpdateView
|
@implementation KBAppUpdateView
|
||||||
@@ -50,6 +52,7 @@
|
|||||||
[self.versionBadgeView addSubview:self.versionLabel];
|
[self.versionBadgeView addSubview:self.versionLabel];
|
||||||
[self addSubview:self.contentTitleLabel];
|
[self addSubview:self.contentTitleLabel];
|
||||||
[self addSubview:self.contentLabel];
|
[self addSubview:self.contentLabel];
|
||||||
|
[self addSubview:self.cancelButton];
|
||||||
[self addSubview:self.upgradeButton];
|
[self addSubview:self.upgradeButton];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +68,7 @@
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
[self.versionBadgeView mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.versionBadgeView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.left.equalTo(self).offset(KBFit(45.0));
|
make.left.equalTo(self).offset(KBFit(18));
|
||||||
make.top.equalTo(self).offset(KBFit(120.0));
|
make.top.equalTo(self).offset(KBFit(120.0));
|
||||||
make.width.mas_equalTo(KBFit(73.0));
|
make.width.mas_equalTo(KBFit(73.0));
|
||||||
make.height.mas_equalTo(KBFit(23.0));
|
make.height.mas_equalTo(KBFit(23.0));
|
||||||
@@ -76,24 +79,19 @@
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
[self.contentTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.contentTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.left.equalTo(self).offset(KBFit(45.0));
|
make.left.equalTo(self.versionBadgeView);
|
||||||
make.top.equalTo(self).offset(KBFit(181.0));
|
make.top.equalTo(self.versionBadgeView.mas_bottom).offset(KBFit(15));
|
||||||
make.right.lessThanOrEqualTo(self).offset(-KBFit(20.0));
|
make.right.lessThanOrEqualTo(self).offset(-KBFit(20.0));
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.left.equalTo(self).offset(KBFit(45.0));
|
make.left.equalTo(self.contentTitleLabel);
|
||||||
make.top.equalTo(self.contentTitleLabel.mas_bottom).offset(KBFit(8.0));
|
make.top.equalTo(self.contentTitleLabel.mas_bottom).offset(KBFit(8.0));
|
||||||
make.right.lessThanOrEqualTo(self).offset(-KBFit(20.0));
|
make.right.lessThanOrEqualTo(self).offset(-KBFit(18));
|
||||||
make.bottom.lessThanOrEqualTo(self.upgradeButton.mas_top).offset(-KBFit(16.0));
|
make.bottom.lessThanOrEqualTo(self.upgradeButton.mas_top).offset(-KBFit(16.0));
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[self.upgradeButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self kb_updateButtonsLayout];
|
||||||
make.centerX.equalTo(self);
|
|
||||||
make.bottom.equalTo(self).offset(-KBFit(12.0));
|
|
||||||
make.width.mas_equalTo(KBFit(230.0));
|
|
||||||
make.height.mas_equalTo(KBFit(45.0));
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applyDefaultTexts {
|
- (void)applyDefaultTexts {
|
||||||
@@ -105,6 +103,8 @@
|
|||||||
KBLocalized(@"SSSSSSSSSSSSSSSSSSS")
|
KBLocalized(@"SSSSSSSSSSSSSSSSSSS")
|
||||||
];
|
];
|
||||||
self.upgradeButtonTitle = KBLocalized(@"立即升级");
|
self.upgradeButtonTitle = KBLocalized(@"立即升级");
|
||||||
|
self.cancelButtonTitle = KBLocalized(@"取消");
|
||||||
|
self.showsCancelButton = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Actions
|
#pragma mark - Actions
|
||||||
@@ -115,6 +115,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)onTapCancel {
|
||||||
|
if ([self.delegate respondsToSelector:@selector(appUpdateViewDidTapCancel:)]) {
|
||||||
|
[self.delegate appUpdateViewDidTapCancel:self];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Setters
|
#pragma mark - Setters
|
||||||
|
|
||||||
- (void)setBackgroundImageName:(NSString *)backgroundImageName {
|
- (void)setBackgroundImageName:(NSString *)backgroundImageName {
|
||||||
@@ -151,6 +157,34 @@
|
|||||||
[self.upgradeButton setTitle:_upgradeButtonTitle forState:UIControlStateNormal];
|
[self.upgradeButton setTitle:_upgradeButtonTitle forState:UIControlStateNormal];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setCancelButtonTitle:(NSString *)cancelButtonTitle {
|
||||||
|
_cancelButtonTitle = [cancelButtonTitle copy];
|
||||||
|
[self.cancelButton setTitle:_cancelButtonTitle forState:UIControlStateNormal];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setShowsCancelButton:(BOOL)showsCancelButton {
|
||||||
|
_showsCancelButton = showsCancelButton;
|
||||||
|
[self kb_updateButtonsLayout];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setUpdateInfo:(KBAppUpdateInfo *)updateInfo {
|
||||||
|
_updateInfo = updateInfo;
|
||||||
|
if (!updateInfo) { return; }
|
||||||
|
self.showsCancelButton = !updateInfo.forceUpdate;
|
||||||
|
if (!updateInfo.forceUpdate) {
|
||||||
|
self.cancelButtonTitle = KBLocalized(@"取消");
|
||||||
|
}
|
||||||
|
self.upgradeButtonTitle = KBLocalized(@"更新");
|
||||||
|
self.contentTitleText = KBLocalized(@"更新内容");
|
||||||
|
NSString *versionName = updateInfo.latestVersionName ?: @"";
|
||||||
|
if (versionName.length > 0 && ![versionName hasPrefix:@"V"] && ![versionName hasPrefix:@"v"]) {
|
||||||
|
versionName = [NSString stringWithFormat:@"V%@", versionName];
|
||||||
|
}
|
||||||
|
self.versionText = versionName ?: @"";
|
||||||
|
NSArray<NSString *> *items = [self kb_contentItemsFromText:updateInfo.releaseNotes];
|
||||||
|
self.contentItems = items;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Helpers
|
#pragma mark - Helpers
|
||||||
|
|
||||||
- (NSString *)formattedContentItems:(NSArray<NSString *> *)items {
|
- (NSString *)formattedContentItems:(NSArray<NSString *> *)items {
|
||||||
@@ -168,6 +202,55 @@
|
|||||||
return [lines componentsJoinedByString:@"\n"];
|
return [lines componentsJoinedByString:@"\n"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray<NSString *> *)kb_contentItemsFromText:(nullable NSString *)text {
|
||||||
|
if (![text isKindOfClass:NSString.class]) { return @[]; }
|
||||||
|
NSString *trimmed = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||||
|
if (trimmed.length == 0) { return @[]; }
|
||||||
|
NSCharacterSet *splitSet = [NSCharacterSet characterSetWithCharactersInString:@"\n;"];
|
||||||
|
NSArray<NSString *> *parts = [trimmed componentsSeparatedByCharactersInSet:splitSet];
|
||||||
|
NSMutableArray<NSString *> *items = [NSMutableArray array];
|
||||||
|
for (NSString *part in parts) {
|
||||||
|
NSString *piece = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||||
|
if (piece.length > 0) {
|
||||||
|
[items addObject:piece];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items.count > 0 ? items : @[trimmed];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)kb_updateButtonsLayout {
|
||||||
|
if (self.showsCancelButton) {
|
||||||
|
self.cancelButton.hidden = NO;
|
||||||
|
[self.cancelButton mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.equalTo(self).offset(KBFit(24.0));
|
||||||
|
make.bottom.equalTo(self).offset(-KBFit(12.0));
|
||||||
|
make.height.mas_equalTo(KBFit(45.0));
|
||||||
|
}];
|
||||||
|
[self.upgradeButton mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.equalTo(self.cancelButton.mas_right).offset(KBFit(12.0));
|
||||||
|
make.right.equalTo(self).offset(-KBFit(24.0));
|
||||||
|
make.bottom.equalTo(self.cancelButton);
|
||||||
|
make.height.equalTo(self.cancelButton);
|
||||||
|
make.width.equalTo(self.cancelButton);
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
self.cancelButton.hidden = YES;
|
||||||
|
[self.cancelButton mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.equalTo(self);
|
||||||
|
make.bottom.equalTo(self).offset(-KBFit(12.0));
|
||||||
|
make.width.mas_equalTo(0.0);
|
||||||
|
make.height.mas_equalTo(0.0);
|
||||||
|
}];
|
||||||
|
[self.upgradeButton mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.equalTo(self);
|
||||||
|
make.bottom.equalTo(self).offset(-KBFit(12.0));
|
||||||
|
make.width.mas_equalTo(KBFit(230.0));
|
||||||
|
make.height.mas_equalTo(KBFit(45.0));
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
[self layoutIfNeeded];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Lazy
|
#pragma mark - Lazy
|
||||||
|
|
||||||
- (UIImageView *)backgroundImageView {
|
- (UIImageView *)backgroundImageView {
|
||||||
@@ -241,4 +324,19 @@
|
|||||||
return _upgradeButton;
|
return _upgradeButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (UIButton *)cancelButton {
|
||||||
|
if (!_cancelButton) {
|
||||||
|
_cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
_cancelButton.backgroundColor = [UIColor whiteColor];
|
||||||
|
_cancelButton.layer.cornerRadius = KBFit(22.5);
|
||||||
|
_cancelButton.layer.masksToBounds = YES;
|
||||||
|
_cancelButton.layer.borderWidth = KB_ONE_PIXEL;
|
||||||
|
_cancelButton.layer.borderColor = [UIColor colorWithHex:0x002339].CGColor;
|
||||||
|
_cancelButton.titleLabel.font = [KBFont bold:14.0];
|
||||||
|
[_cancelButton setTitleColor:[UIColor colorWithHex:0x002339] forState:UIControlStateNormal];
|
||||||
|
[_cancelButton addTarget:self action:@selector(onTapCancel) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
}
|
||||||
|
return _cancelButton;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -14,7 +14,27 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
typedef void(^KBLoginCompletion)(BOOL success, NSError * _Nullable error);
|
typedef void(^KBLoginCompletion)(BOOL success, NSError * _Nullable error);
|
||||||
typedef void(^KBRegisterCompletion)(BOOL success, NSError * _Nullable error);
|
typedef void(^KBRegisterCompletion)(BOOL success, NSError * _Nullable error);
|
||||||
typedef void(^KBVerifyMailCompletion)(BOOL success, NSError * _Nullable error);
|
typedef void(^KBVerifyMailCompletion)(BOOL success, NSError * _Nullable error);
|
||||||
typedef void(^KBAppUpdateCompletion)(NSDictionary * _Nullable data, NSError * _Nullable error);
|
|
||||||
|
@class KBAppUpdateInfo;
|
||||||
|
@class KBAppUpdateResponse;
|
||||||
|
typedef void(^KBAppUpdateCompletion)(KBAppUpdateInfo * _Nullable info, NSError * _Nullable error);
|
||||||
|
|
||||||
|
@interface KBAppUpdateInfo : NSObject
|
||||||
|
@property (nonatomic, assign) NSInteger minSupportedCode;
|
||||||
|
@property (nonatomic, copy, nullable) NSString *latestVersionName;
|
||||||
|
@property (nonatomic, copy, nullable) NSString *downloadUrl;
|
||||||
|
@property (nonatomic, assign) BOOL needUpdate;
|
||||||
|
@property (nonatomic, assign) NSInteger latestVersionCode;
|
||||||
|
@property (nonatomic, assign) BOOL forceUpdate;
|
||||||
|
@property (nonatomic, copy, nullable) NSString *releaseNotes;
|
||||||
|
@property (nonatomic, copy, nullable) NSString *storeUrl;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface KBAppUpdateResponse : NSObject
|
||||||
|
@property (nonatomic, assign) NSInteger code;
|
||||||
|
@property (nonatomic, copy, nullable) NSString *message;
|
||||||
|
@property (nonatomic, strong, nullable) KBAppUpdateInfo *data;
|
||||||
|
@end
|
||||||
|
|
||||||
@interface KBLoginVM : NSObject
|
@interface KBLoginVM : NSObject
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,12 @@
|
|||||||
@property (nonatomic, strong) KBMyVM *myVM;
|
@property (nonatomic, strong) KBMyVM *myVM;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation KBAppUpdateInfo
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation KBAppUpdateResponse
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation KBLoginVM
|
@implementation KBLoginVM
|
||||||
|
|
||||||
+ (instancetype)shared {
|
+ (instancetype)shared {
|
||||||
@@ -169,7 +175,10 @@
|
|||||||
NSDictionary *params = [self kb_appUpdateParams];
|
NSDictionary *params = [self kb_appUpdateParams];
|
||||||
[[KBNetworkManager shared] POST:API_APP_CHECK_UPDATE jsonBody:params headers:nil autoShowBusinessError:NO completion:^(NSDictionary * _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
[[KBNetworkManager shared] POST:API_APP_CHECK_UPDATE jsonBody:params headers:nil autoShowBusinessError:NO completion:^(NSDictionary * _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||||
if (error) { if (completion) completion(nil, error); return; }
|
if (error) { if (completion) completion(nil, error); return; }
|
||||||
if (completion) completion(jsonOrData, nil);
|
if (![jsonOrData isKindOfClass:NSDictionary.class]) { if (completion) completion(nil, nil); return; }
|
||||||
|
KBAppUpdateResponse *resp = [KBAppUpdateResponse mj_objectWithKeyValues:jsonOrData];
|
||||||
|
if (resp.code != 0) { if (completion) completion(nil, nil); return; }
|
||||||
|
if (completion) completion(resp.data, nil);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user