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

@@ -32,7 +32,7 @@
// 基础baseUrl // 基础baseUrl
#ifndef KB_BASE_URL #ifndef KB_BASE_URL
//#define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/" //#define KB_BASE_URL @"https://m1.apifoxmock.com/m1/5438099-5113192-default/"
#define KB_BASE_URL @"http://192.168.1.144:7529/api" #define KB_BASE_URL @"http://192.168.2.21:7529/api"
#endif #endif
#import "KBFont.h" #import "KBFont.h"

View File

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