2025-12-02 18:29:04 +08:00
|
|
|
|
//
|
|
|
|
|
|
// KBLoginVC.m
|
|
|
|
|
|
// keyBoard
|
|
|
|
|
|
//
|
|
|
|
|
|
// Created by Mac on 2025/12/2.
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#import "KBLoginVC.h"
|
|
|
|
|
|
#import <AuthenticationServices/AuthenticationServices.h>
|
2025-12-02 19:19:25 +08:00
|
|
|
|
#import "KBLoginVM.h"
|
2025-12-02 18:29:04 +08:00
|
|
|
|
|
2025-12-02 19:19:25 +08:00
|
|
|
|
@interface KBLoginVC () <UITextViewDelegate>
|
2025-12-02 18:29:04 +08:00
|
|
|
|
|
|
|
|
|
|
// 背景
|
|
|
|
|
|
@property (nonatomic, strong) UIImageView *bgImageView; // 整体背景图:login_bg_icon
|
|
|
|
|
|
@property (nonatomic, strong) UIImageView *topRightImageView; // 顶部右侧装饰图:login_jianp_icon
|
|
|
|
|
|
|
|
|
|
|
|
// 底部白色容器(仅上圆角 26)
|
|
|
|
|
|
@property (nonatomic, strong) UIView *contentContainerView;
|
|
|
|
|
|
|
|
|
|
|
|
// 标题
|
|
|
|
|
|
@property (nonatomic, strong) UILabel *titleLabel;
|
|
|
|
|
|
|
|
|
|
|
|
// 按钮
|
|
|
|
|
|
@property (nonatomic, strong) UIControl *appleLoginButton; // Apple 原生登录按钮(iOS13 以下降级为普通按钮)
|
|
|
|
|
|
@property (nonatomic, strong) UIButton *emailLoginButton; // 邮箱登录按钮
|
|
|
|
|
|
|
|
|
|
|
|
// 协议 & 底部文案
|
2025-12-02 19:19:25 +08:00
|
|
|
|
@property (nonatomic, strong) UITextView *agreementTextView; // 底部协议富文本
|
2025-12-02 18:29:04 +08:00
|
|
|
|
|
|
|
|
|
|
@property (nonatomic, strong) UILabel *noAccountLabel; // “Don't Have An Account?”
|
|
|
|
|
|
@property (nonatomic, strong) UIButton *signUpButton; // “Sign Up”
|
|
|
|
|
|
@property (nonatomic, strong) UIButton *forgotPasswordButton; // “Forgot Password?”
|
|
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@implementation KBLoginVC
|
|
|
|
|
|
|
|
|
|
|
|
- (void)viewDidLoad {
|
|
|
|
|
|
[super viewDidLoad];
|
|
|
|
|
|
// 使用全屏内容,隐藏自定义导航栏
|
|
|
|
|
|
self.kb_enableCustomNavBar = NO;
|
|
|
|
|
|
self.view.backgroundColor = [UIColor whiteColor];
|
|
|
|
|
|
|
|
|
|
|
|
[self setupUI];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)viewDidLayoutSubviews {
|
|
|
|
|
|
[super viewDidLayoutSubviews];
|
|
|
|
|
|
// 仅白色容器的左上、右上圆角为 26
|
|
|
|
|
|
if (!CGRectIsEmpty(self.contentContainerView.bounds)) {
|
|
|
|
|
|
UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight;
|
|
|
|
|
|
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.contentContainerView.bounds
|
|
|
|
|
|
byRoundingCorners:corners
|
|
|
|
|
|
cornerRadii:CGSizeMake(26, 26)];
|
|
|
|
|
|
CAShapeLayer *mask = [CAShapeLayer layer];
|
|
|
|
|
|
mask.frame = self.contentContainerView.bounds;
|
|
|
|
|
|
mask.path = path.CGPath;
|
|
|
|
|
|
self.contentContainerView.layer.mask = mask;
|
|
|
|
|
|
}
|
2025-12-02 19:19:25 +08:00
|
|
|
|
|
|
|
|
|
|
// 让按钮内部的图片+文字整体居中,图片与文字间距为 50(按设计稿缩放)
|
|
|
|
|
|
// if (self.emailLoginButton.currentImage && self.emailLoginButton.currentTitle.length > 0) {
|
|
|
|
|
|
// [self kb_centerImageAndTitleForButton:self.emailLoginButton spacing:KBFit(50)];
|
|
|
|
|
|
// }
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - UI
|
|
|
|
|
|
|
|
|
|
|
|
- (void)setupUI {
|
|
|
|
|
|
// 背景图
|
|
|
|
|
|
[self.view addSubview:self.bgImageView];
|
|
|
|
|
|
[self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.edges.equalTo(self.view);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 顶部右侧装饰图
|
|
|
|
|
|
[self.view addSubview:self.topRightImageView];
|
|
|
|
|
|
[self.topRightImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.top.equalTo(self.view).offset(KB_StatusBarHeight() + KBFit(24));
|
|
|
|
|
|
make.right.equalTo(self.view).offset(-KBFit(20));
|
|
|
|
|
|
make.width.mas_equalTo(KBFit(244));
|
|
|
|
|
|
make.height.mas_equalTo(KBFit(224));
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 底部白色容器
|
|
|
|
|
|
[self.view addSubview:self.contentContainerView];
|
|
|
|
|
|
[self.contentContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.right.bottom.equalTo(self.view);
|
|
|
|
|
|
// 顶部位置大致贴合设计稿,可根据实际效果微调
|
2025-12-02 19:19:25 +08:00
|
|
|
|
make.top.equalTo(self.view).offset(KBFit(272));
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 标题
|
|
|
|
|
|
[self.contentContainerView addSubview:self.titleLabel];
|
|
|
|
|
|
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
2025-12-02 19:19:25 +08:00
|
|
|
|
make.top.equalTo(self.contentContainerView).offset(27);
|
2025-12-02 18:29:04 +08:00
|
|
|
|
make.centerX.equalTo(self.contentContainerView);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// Apple 登录按钮
|
|
|
|
|
|
[self.contentContainerView addSubview:self.appleLoginButton];
|
|
|
|
|
|
[self.appleLoginButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.top.equalTo(self.titleLabel.mas_bottom).offset(24);
|
|
|
|
|
|
make.left.equalTo(self.contentContainerView).offset(30);
|
|
|
|
|
|
make.right.equalTo(self.contentContainerView).offset(-30);
|
|
|
|
|
|
make.height.mas_equalTo(52);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 邮箱登录按钮
|
|
|
|
|
|
[self.contentContainerView addSubview:self.emailLoginButton];
|
|
|
|
|
|
[self.emailLoginButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
2025-12-02 19:19:25 +08:00
|
|
|
|
make.top.equalTo(self.appleLoginButton.mas_bottom).offset(15);
|
2025-12-02 18:29:04 +08:00
|
|
|
|
make.left.right.height.equalTo(self.appleLoginButton);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
2025-12-02 19:19:25 +08:00
|
|
|
|
// 底部协议文案(单个富文本视图,内部 terms/privacy 文案可点击)
|
|
|
|
|
|
[self.contentContainerView addSubview:self.agreementTextView];
|
|
|
|
|
|
[self.agreementTextView mas_makeConstraints:^(MASConstraintMaker *make) {
|
2025-12-02 18:29:04 +08:00
|
|
|
|
make.centerX.equalTo(self.contentContainerView);
|
2025-12-02 19:19:25 +08:00
|
|
|
|
make.left.greaterThanOrEqualTo(self.contentContainerView).offset(30);
|
|
|
|
|
|
make.right.lessThanOrEqualTo(self.contentContainerView).offset(-30);
|
2025-12-02 18:29:04 +08:00
|
|
|
|
make.bottom.equalTo(self.contentContainerView).offset(-KB_SAFE_BOTTOM - 84);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// 底部账号相关文案
|
|
|
|
|
|
UIButton *forgot = self.forgotPasswordButton;
|
|
|
|
|
|
[self.contentContainerView addSubview:forgot];
|
|
|
|
|
|
[forgot mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.centerX.equalTo(self.contentContainerView);
|
|
|
|
|
|
make.bottom.equalTo(self.contentContainerView).offset(-KB_SAFE_BOTTOM - 24);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
UIView *accountLine = [UIView new];
|
|
|
|
|
|
[self.contentContainerView addSubview:accountLine];
|
|
|
|
|
|
[accountLine mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.centerX.equalTo(self.contentContainerView);
|
|
|
|
|
|
make.bottom.equalTo(forgot.mas_top).offset(-8);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
[accountLine addSubview:self.noAccountLabel];
|
|
|
|
|
|
[accountLine addSubview:self.signUpButton];
|
|
|
|
|
|
|
|
|
|
|
|
[self.noAccountLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.top.left.bottom.equalTo(accountLine);
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
[self.signUpButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
|
|
|
make.left.equalTo(self.noAccountLabel.mas_right).offset(4);
|
|
|
|
|
|
make.right.equalTo(accountLine);
|
|
|
|
|
|
make.centerY.equalTo(self.noAccountLabel);
|
|
|
|
|
|
}];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Actions
|
|
|
|
|
|
|
|
|
|
|
|
- (void)onTapAppleLogin {
|
|
|
|
|
|
// 后续可接入 Apple Sign-In 逻辑,这里先占位
|
2025-12-02 19:19:25 +08:00
|
|
|
|
KBLOG(@"onTapAppleLogin");
|
|
|
|
|
|
[[KBLoginVM shared] signInWithAppleFromViewController:KB_CURRENT_NAV completion:^(BOOL success, NSError * _Nullable error) {
|
|
|
|
|
|
if (success) {
|
|
|
|
|
|
[KBHUD showInfo:KBLocalized(@"Signed in successfully")];
|
|
|
|
|
|
} else {
|
|
|
|
|
|
NSString *msg = error.localizedDescription ?: KBLocalized(@"Sign-in failed");
|
|
|
|
|
|
[KBHUD showInfo:msg];
|
|
|
|
|
|
}
|
|
|
|
|
|
}];
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)onTapEmailLogin {
|
|
|
|
|
|
// 后续接入邮箱登录逻辑
|
2025-12-02 19:19:25 +08:00
|
|
|
|
KBLOG(@"onTapEmailLogin");
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)onTapPolicy {
|
|
|
|
|
|
// 打开服务条款/隐私政策
|
2025-12-02 19:19:25 +08:00
|
|
|
|
KBLOG(@"onTapPolicy");
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)onTapSignUp {
|
|
|
|
|
|
// 打开注册页
|
2025-12-02 19:19:25 +08:00
|
|
|
|
KBLOG(@"onTapSignUp");
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (void)onTapForgotPassword {
|
|
|
|
|
|
// 打开忘记密码页
|
2025-12-02 19:19:25 +08:00
|
|
|
|
KBLOG(@"onTapForgotPassword");
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Lazy UI
|
|
|
|
|
|
|
|
|
|
|
|
- (UIImageView *)bgImageView {
|
|
|
|
|
|
if (!_bgImageView) {
|
|
|
|
|
|
_bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"login_bg_icon"]];
|
|
|
|
|
|
_bgImageView.contentMode = UIViewContentModeScaleAspectFill;
|
|
|
|
|
|
_bgImageView.clipsToBounds = YES;
|
|
|
|
|
|
}
|
|
|
|
|
|
return _bgImageView;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIImageView *)topRightImageView {
|
|
|
|
|
|
if (!_topRightImageView) {
|
|
|
|
|
|
_topRightImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"login_jianp_icon"]];
|
|
|
|
|
|
_topRightImageView.contentMode = UIViewContentModeScaleAspectFit;
|
|
|
|
|
|
_topRightImageView.clipsToBounds = YES;
|
|
|
|
|
|
}
|
|
|
|
|
|
return _topRightImageView;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIView *)contentContainerView {
|
|
|
|
|
|
if (!_contentContainerView) {
|
|
|
|
|
|
_contentContainerView = [UIView new];
|
|
|
|
|
|
_contentContainerView.backgroundColor = [UIColor whiteColor];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _contentContainerView;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UILabel *)titleLabel {
|
|
|
|
|
|
if (!_titleLabel) {
|
|
|
|
|
|
_titleLabel = [UILabel new];
|
|
|
|
|
|
_titleLabel.text = KBLocalized(@"Log In To Key Of Love");
|
|
|
|
|
|
_titleLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
|
|
|
|
|
_titleLabel.font = [KBFont bold:18];
|
|
|
|
|
|
_titleLabel.textAlignment = NSTextAlignmentCenter;
|
|
|
|
|
|
}
|
|
|
|
|
|
return _titleLabel;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIControl *)appleLoginButton {
|
|
|
|
|
|
if (!_appleLoginButton) {
|
|
|
|
|
|
ASAuthorizationAppleIDButton *btn = [ASAuthorizationAppleIDButton buttonWithType:ASAuthorizationAppleIDButtonTypeSignIn
|
|
|
|
|
|
style:ASAuthorizationAppleIDButtonStyleWhite];
|
|
|
|
|
|
[btn addTarget:self action:@selector(onTapAppleLogin) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
|
|
btn.cornerRadius = 10.0;
|
|
|
|
|
|
btn.layer.borderColor = [UIColor colorWithHex:0xE5E5E5].CGColor;
|
|
|
|
|
|
btn.layer.borderWidth = 1;
|
2025-12-02 19:19:25 +08:00
|
|
|
|
btn.layer.cornerRadius = 10.0;
|
|
|
|
|
|
btn.layer.masksToBounds = true;
|
2025-12-02 18:29:04 +08:00
|
|
|
|
_appleLoginButton = btn;
|
|
|
|
|
|
}
|
|
|
|
|
|
return _appleLoginButton;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIButton *)emailLoginButton {
|
|
|
|
|
|
if (!_emailLoginButton) {
|
|
|
|
|
|
_emailLoginButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
|
|
[_emailLoginButton setTitle:KBLocalized(@"Continue Via Email") forState:UIControlStateNormal];
|
|
|
|
|
|
[_emailLoginButton setTitleColor:[UIColor colorWithHex:KBBlackValue] forState:UIControlStateNormal];
|
|
|
|
|
|
_emailLoginButton.titleLabel.font = [KBFont medium:16];
|
2025-12-02 19:19:25 +08:00
|
|
|
|
// _emailLoginButton.backgroundColor = [UIColor colorWithHex:0xF7F7F7];
|
2025-12-02 18:29:04 +08:00
|
|
|
|
_emailLoginButton.layer.cornerRadius = 10.0;
|
|
|
|
|
|
_emailLoginButton.layer.masksToBounds = YES;
|
2025-12-02 19:19:25 +08:00
|
|
|
|
_emailLoginButton.layer.borderColor = [UIColor colorWithHex:0xE5E5E5].CGColor;
|
|
|
|
|
|
_emailLoginButton.layer.borderWidth = 1;
|
|
|
|
|
|
_emailLoginButton.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
|
|
|
|
|
|
_emailLoginButton.titleEdgeInsets = UIEdgeInsetsMake(0, 15, 0, 0);
|
|
|
|
|
|
|
2025-12-02 18:29:04 +08:00
|
|
|
|
UIImage *icon = [UIImage imageNamed:@"login_email_icon"];
|
|
|
|
|
|
if (icon) {
|
2025-12-02 19:19:25 +08:00
|
|
|
|
// 将邮箱图标缩小一点,让视觉上更接近系统 Apple 按钮的图标大小
|
|
|
|
|
|
CGFloat targetHeight = 12; // 设计上略小于按钮高度
|
|
|
|
|
|
CGFloat scale = targetHeight / icon.size.height;
|
|
|
|
|
|
CGSize targetSize = CGSizeMake(icon.size.width * scale, targetHeight);
|
|
|
|
|
|
|
|
|
|
|
|
UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0.0);
|
|
|
|
|
|
[icon drawInRect:CGRectMake(0, 0, targetSize.width, targetSize.height)];
|
|
|
|
|
|
UIImage *scaledIcon = UIGraphicsGetImageFromCurrentImageContext();
|
|
|
|
|
|
UIGraphicsEndImageContext();
|
|
|
|
|
|
|
|
|
|
|
|
[_emailLoginButton setImage:scaledIcon forState:UIControlStateNormal];
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[_emailLoginButton addTarget:self action:@selector(onTapEmailLogin) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _emailLoginButton;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-02 19:19:25 +08:00
|
|
|
|
- (UITextView *)agreementTextView {
|
|
|
|
|
|
if (!_agreementTextView) {
|
|
|
|
|
|
_agreementTextView = [UITextView new];
|
|
|
|
|
|
_agreementTextView.backgroundColor = [UIColor clearColor];
|
|
|
|
|
|
_agreementTextView.editable = NO; // 不可编辑
|
|
|
|
|
|
_agreementTextView.selectable = NO; // 不可选中文本
|
|
|
|
|
|
_agreementTextView.scrollEnabled = NO;
|
|
|
|
|
|
_agreementTextView.textAlignment = NSTextAlignmentCenter;
|
|
|
|
|
|
_agreementTextView.textContainerInset = UIEdgeInsetsZero;
|
|
|
|
|
|
_agreementTextView.textContainer.lineFragmentPadding = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 协议文案:terms of service / privacy policy 为纯黑色并可点击,其余为 #717171
|
|
|
|
|
|
NSString *fullText = @"By continuing, you agree to our terms of service and confirm that you have read our privacy policy";
|
|
|
|
|
|
NSString *termsText = @"terms of service";
|
|
|
|
|
|
NSString *privacyText = @"privacy policy";
|
|
|
|
|
|
|
|
|
|
|
|
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:fullText
|
|
|
|
|
|
attributes:@{
|
|
|
|
|
|
NSFontAttributeName : [KBFont regular:12],
|
|
|
|
|
|
NSForegroundColorAttributeName : [UIColor colorWithHex:0x717171]
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
NSString *lowerFull = fullText.lowercaseString;
|
|
|
|
|
|
NSRange termsRange = [lowerFull rangeOfString:termsText.lowercaseString];
|
|
|
|
|
|
if (termsRange.location != NSNotFound) {
|
|
|
|
|
|
[attr addAttributes:@{
|
|
|
|
|
|
NSForegroundColorAttributeName : [UIColor colorWithHex:KBBlackValue],
|
|
|
|
|
|
NSUnderlineStyleAttributeName : @(NSUnderlineStyleNone)
|
|
|
|
|
|
} range:termsRange];
|
|
|
|
|
|
}
|
2025-12-02 18:29:04 +08:00
|
|
|
|
|
2025-12-02 19:19:25 +08:00
|
|
|
|
NSRange privacyRange = [lowerFull rangeOfString:privacyText.lowercaseString];
|
|
|
|
|
|
if (privacyRange.location != NSNotFound) {
|
|
|
|
|
|
[attr addAttributes:@{
|
|
|
|
|
|
NSForegroundColorAttributeName : [UIColor colorWithHex:KBBlackValue],
|
|
|
|
|
|
NSUnderlineStyleAttributeName : @(NSUnderlineStyleNone)
|
|
|
|
|
|
} range:privacyRange];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_agreementTextView.linkTextAttributes = @{
|
|
|
|
|
|
NSForegroundColorAttributeName : [UIColor colorWithHex:KBBlackValue],
|
|
|
|
|
|
NSUnderlineStyleAttributeName : @(NSUnderlineStyleNone)
|
|
|
|
|
|
};
|
|
|
|
|
|
_agreementTextView.attributedText = attr;
|
|
|
|
|
|
|
|
|
|
|
|
// 自定义点击识别,避免系统选择/复制
|
|
|
|
|
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(kb_handleAgreementTap:)];
|
|
|
|
|
|
_agreementTextView.userInteractionEnabled = YES;
|
|
|
|
|
|
[_agreementTextView addGestureRecognizer:tap];
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
2025-12-02 19:19:25 +08:00
|
|
|
|
return _agreementTextView;
|
2025-12-02 18:29:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UILabel *)noAccountLabel {
|
|
|
|
|
|
if (!_noAccountLabel) {
|
|
|
|
|
|
_noAccountLabel = [UILabel new];
|
|
|
|
|
|
_noAccountLabel.text = KBLocalized(@"Don't Have An Account?");
|
|
|
|
|
|
_noAccountLabel.font = [KBFont regular:13];
|
|
|
|
|
|
_noAccountLabel.textColor = [UIColor colorWithWhite:0.45 alpha:1.0];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _noAccountLabel;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIButton *)signUpButton {
|
|
|
|
|
|
if (!_signUpButton) {
|
|
|
|
|
|
_signUpButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
|
|
[_signUpButton setTitle:KBLocalized(@"Sign Up") forState:UIControlStateNormal];
|
|
|
|
|
|
[_signUpButton setTitleColor:[UIColor colorWithHex:KBColorValue] forState:UIControlStateNormal];
|
|
|
|
|
|
_signUpButton.titleLabel.font = [KBFont medium:13];
|
|
|
|
|
|
[_signUpButton addTarget:self action:@selector(onTapSignUp) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _signUpButton;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- (UIButton *)forgotPasswordButton {
|
|
|
|
|
|
if (!_forgotPasswordButton) {
|
|
|
|
|
|
_forgotPasswordButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
|
|
[_forgotPasswordButton setTitle:KBLocalized(@"Forgot Password?") forState:UIControlStateNormal];
|
|
|
|
|
|
[_forgotPasswordButton setTitleColor:[UIColor colorWithHex:KBColorValue] forState:UIControlStateNormal];
|
|
|
|
|
|
_forgotPasswordButton.titleLabel.font = [KBFont regular:13];
|
|
|
|
|
|
[_forgotPasswordButton addTarget:self action:@selector(onTapForgotPassword) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
|
|
}
|
|
|
|
|
|
return _forgotPasswordButton;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-02 19:19:25 +08:00
|
|
|
|
#pragma mark - Helper
|
|
|
|
|
|
|
|
|
|
|
|
/// 让按钮内部图片和文字整体居中,并设置固定间距(spacing 为设计稿值,调用时已做 KBFit)
|
|
|
|
|
|
- (void)kb_centerImageAndTitleForButton:(UIButton *)button spacing:(CGFloat)spacing {
|
|
|
|
|
|
if (!button.currentImage || button.currentTitle.length == 0) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
|
|
|
|
|
|
|
|
|
|
|
|
CGSize imageSize = button.imageView.image.size;
|
|
|
|
|
|
CGSize titleSize = button.titleLabel.intrinsicContentSize;
|
|
|
|
|
|
CGFloat totalWidth = imageSize.width + spacing + titleSize.width;
|
|
|
|
|
|
|
|
|
|
|
|
CGFloat imageOffsetX = -(totalWidth / 2.0 - imageSize.width / 2.0);
|
|
|
|
|
|
CGFloat titleOffsetX = totalWidth / 2.0 - titleSize.width / 2.0;
|
|
|
|
|
|
|
|
|
|
|
|
button.imageEdgeInsets = UIEdgeInsetsMake(0, imageOffsetX, 0, -imageOffsetX);
|
|
|
|
|
|
button.titleEdgeInsets = UIEdgeInsetsMake(0, titleOffsetX, 0, -titleOffsetX);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Agreement Tap
|
|
|
|
|
|
|
|
|
|
|
|
- (void)kb_handleAgreementTap:(UITapGestureRecognizer *)tap {
|
|
|
|
|
|
UITextView *textView = self.agreementTextView;
|
|
|
|
|
|
CGPoint point = [tap locationInView:textView];
|
|
|
|
|
|
|
|
|
|
|
|
// 将点击点转换到 textContainer 坐标系
|
|
|
|
|
|
CGPoint location = point;
|
|
|
|
|
|
location.x -= textView.textContainerInset.left;
|
|
|
|
|
|
location.y -= textView.textContainerInset.top;
|
|
|
|
|
|
|
|
|
|
|
|
NSLayoutManager *layoutManager = textView.layoutManager;
|
|
|
|
|
|
NSTextContainer *textContainer = textView.textContainer;
|
|
|
|
|
|
NSUInteger glyphIndex = [layoutManager glyphIndexForPoint:location
|
|
|
|
|
|
inTextContainer:textContainer];
|
|
|
|
|
|
if (glyphIndex >= textView.textStorage.length) { return; }
|
|
|
|
|
|
|
|
|
|
|
|
NSUInteger charIndex = [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
|
|
|
|
|
|
|
|
|
|
|
|
NSString *lowerFull = textView.text.lowercaseString ?: @"";
|
|
|
|
|
|
NSRange termsRange = [lowerFull rangeOfString:@"terms of service"];
|
|
|
|
|
|
NSRange privacyRange = [lowerFull rangeOfString:@"privacy policy"];
|
|
|
|
|
|
|
|
|
|
|
|
BOOL hitTerms = (termsRange.location != NSNotFound && NSLocationInRange(charIndex, termsRange));
|
|
|
|
|
|
BOOL hitPrivacy = (privacyRange.location != NSNotFound && NSLocationInRange(charIndex, privacyRange));
|
|
|
|
|
|
if (hitTerms || hitPrivacy) {
|
|
|
|
|
|
[self onTapPolicy];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-02 18:29:04 +08:00
|
|
|
|
@end
|