This commit is contained in:
2025-12-02 19:19:25 +08:00
parent 8245e7b3d1
commit 5e4c16c577
2 changed files with 147 additions and 43 deletions

View File

@@ -7,8 +7,9 @@
#import "KBLoginVC.h"
#import <AuthenticationServices/AuthenticationServices.h>
#import "KBLoginVM.h"
@interface KBLoginVC ()
@interface KBLoginVC () <UITextViewDelegate>
//
@property (nonatomic, strong) UIImageView *bgImageView; // login_bg_icon
@@ -25,8 +26,7 @@
@property (nonatomic, strong) UIButton *emailLoginButton; //
// &
@property (nonatomic, strong) UILabel *agreementLabel; // By Continuing, You Agree To Our
@property (nonatomic, strong) UIButton *policyButton; // Terms Of Service & Privacy Policy
@property (nonatomic, strong) UITextView *agreementTextView; //
@property (nonatomic, strong) UILabel *noAccountLabel; // Don't Have An Account?
@property (nonatomic, strong) UIButton *signUpButton; // Sign Up
@@ -58,6 +58,11 @@
mask.path = path.CGPath;
self.contentContainerView.layer.mask = mask;
}
// + 50稿
// if (self.emailLoginButton.currentImage && self.emailLoginButton.currentTitle.length > 0) {
// [self kb_centerImageAndTitleForButton:self.emailLoginButton spacing:KBFit(50)];
// }
}
#pragma mark - UI
@@ -83,13 +88,13 @@
[self.contentContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.equalTo(self.view);
// 稿
make.top.equalTo(self.view).offset(272);
make.top.equalTo(self.view).offset(KBFit(272));
}];
//
[self.contentContainerView addSubview:self.titleLabel];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentContainerView).offset(32);
make.top.equalTo(self.contentContainerView).offset(27);
make.centerX.equalTo(self.contentContainerView);
}];
@@ -105,24 +110,19 @@
//
[self.contentContainerView addSubview:self.emailLoginButton];
[self.emailLoginButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.appleLoginButton.mas_bottom).offset(16);
make.top.equalTo(self.appleLoginButton.mas_bottom).offset(15);
make.left.right.height.equalTo(self.appleLoginButton);
}];
//
[self.contentContainerView addSubview:self.policyButton];
[self.contentContainerView addSubview:self.agreementLabel];
[self.policyButton mas_makeConstraints:^(MASConstraintMaker *make) {
// terms/privacy
[self.contentContainerView addSubview:self.agreementTextView];
[self.agreementTextView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.contentContainerView);
make.left.greaterThanOrEqualTo(self.contentContainerView).offset(30);
make.right.lessThanOrEqualTo(self.contentContainerView).offset(-30);
make.bottom.equalTo(self.contentContainerView).offset(-KB_SAFE_BOTTOM - 84);
}];
[self.agreementLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.contentContainerView);
make.bottom.equalTo(self.policyButton.mas_top).offset(-4);
}];
//
UIButton *forgot = self.forgotPasswordButton;
[self.contentContainerView addSubview:forgot];
@@ -156,22 +156,35 @@
- (void)onTapAppleLogin {
// Apple Sign-In
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];
}
}];
}
- (void)onTapEmailLogin {
//
KBLOG(@"onTapEmailLogin");
}
- (void)onTapPolicy {
// /
KBLOG(@"onTapPolicy");
}
- (void)onTapSignUp {
//
KBLOG(@"onTapSignUp");
}
- (void)onTapForgotPassword {
//
KBLOG(@"onTapForgotPassword");
}
#pragma mark - Lazy UI
@@ -221,6 +234,8 @@
btn.cornerRadius = 10.0;
btn.layer.borderColor = [UIColor colorWithHex:0xE5E5E5].CGColor;
btn.layer.borderWidth = 1;
btn.layer.cornerRadius = 10.0;
btn.layer.masksToBounds = true;
_appleLoginButton = btn;
}
return _appleLoginButton;
@@ -232,17 +247,27 @@
[_emailLoginButton setTitle:KBLocalized(@"Continue Via Email") forState:UIControlStateNormal];
[_emailLoginButton setTitleColor:[UIColor colorWithHex:KBBlackValue] forState:UIControlStateNormal];
_emailLoginButton.titleLabel.font = [KBFont medium:16];
_emailLoginButton.backgroundColor = [UIColor colorWithHex:0xF7F7F7];
// _emailLoginButton.backgroundColor = [UIColor colorWithHex:0xF7F7F7];
_emailLoginButton.layer.cornerRadius = 10.0;
_emailLoginButton.layer.masksToBounds = YES;
_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);
UIImage *icon = [UIImage imageNamed:@"login_email_icon"];
if (icon) {
[_emailLoginButton setImage:icon forState:UIControlStateNormal];
//
_emailLoginButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
_emailLoginButton.imageEdgeInsets = UIEdgeInsetsMake(0, 16, 0, 0);
_emailLoginButton.titleEdgeInsets = UIEdgeInsetsMake(0, 32, 0, 0);
// 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];
}
[_emailLoginButton addTarget:self action:@selector(onTapEmailLogin) forControlEvents:UIControlEventTouchUpInside];
@@ -250,27 +275,57 @@
return _emailLoginButton;
}
- (UILabel *)agreementLabel {
if (!_agreementLabel) {
_agreementLabel = [UILabel new];
_agreementLabel.text = KBLocalized(@"By Continuing, You Agree To Our");
_agreementLabel.font = [KBFont regular:12];
_agreementLabel.textColor = [UIColor colorWithWhite:0.45 alpha:1.0];
_agreementLabel.textAlignment = NSTextAlignmentCenter;
_agreementLabel.numberOfLines = 1;
}
return _agreementLabel;
}
- (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;
- (UIButton *)policyButton {
if (!_policyButton) {
_policyButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_policyButton setTitle:KBLocalized(@"Terms Of Service & Privacy Policy") forState:UIControlStateNormal];
[_policyButton setTitleColor:[UIColor colorWithHex:KBColorValue] forState:UIControlStateNormal];
_policyButton.titleLabel.font = [KBFont regular:12];
[_policyButton addTarget:self action:@selector(onTapPolicy) forControlEvents:UIControlEventTouchUpInside];
// 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];
}
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];
}
return _policyButton;
return _agreementTextView;
}
- (UILabel *)noAccountLabel {
@@ -305,4 +360,53 @@
return _forgotPasswordButton;
}
#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];
}
}
@end