Browse Source

feat: 增加 苹果 账号的登录逻辑

陈文艺 2 months ago
parent
commit
88948fb9c1

+ 4 - 2
Lanu.xcodeproj/project.pbxproj

@@ -531,12 +531,13 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Lanu/Lanu.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 28;
+				CURRENT_PROJECT_VERSION = 30;
 				DEVELOPMENT_TEAM = 5H8D98R72W;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = Lanu/Info.plist;
 				INFOPLIST_KEY_CFBundleDisplayName = "Gami(Debug)";
+				INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
 				INFOPLIST_KEY_NSAccessoryTrackingUsageDescription = "";
 				INFOPLIST_KEY_NSCameraUsageDescription = "need permission";
 				INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = 12;
@@ -579,12 +580,13 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Lanu/Lanu.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 28;
+				CURRENT_PROJECT_VERSION = 30;
 				DEVELOPMENT_TEAM = 5H8D98R72W;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = Lanu/Info.plist;
 				INFOPLIST_KEY_CFBundleDisplayName = Gami;
+				INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
 				INFOPLIST_KEY_NSAccessoryTrackingUsageDescription = "";
 				INFOPLIST_KEY_NSCameraUsageDescription = "need permission";
 				INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = 12;

+ 1 - 1
Lanu.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -1,5 +1,5 @@
 {
-  "originHash" : "16c946624b1532e32f415acfc60c55e8a9ac18a853568ef3fa132a2a8634b7fa",
+  "originHash" : "b2c25fbaf8ba5f006703fea95f1b23e611935d07e0928897c4763edfcf096f44",
   "pins" : [
     {
       "identity" : "abseil-cpp-binary",

+ 22 - 0
Lanu/Assets.xcassets/Login/ic_apple.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ic_apple@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ic_apple@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
Lanu/Assets.xcassets/Login/ic_apple.imageset/ic_apple@2x.png


BIN
Lanu/Assets.xcassets/Login/ic_apple.imageset/ic_apple@3x.png


+ 4 - 2
Lanu/Common/Views/Toast/LNToastView.swift

@@ -37,15 +37,16 @@ class LNToastView: UIView {
     func show(_ toast: String) {
         textLabel.text = toast
         
-        allToast.add(self)
-        
         guard let window = UIView.appKeyWindow else { return }
         window.addSubview(self)
         self.snp.makeConstraints { make in
             make.centerX.equalToSuperview()
+            make.leading.greaterThanOrEqualToSuperview().offset(56)
             make.bottom.equalToSuperview().offset(-331)
         }
         
+        allToast.add(self)
+        
         LNDelayTask.perform(delay: 2.5) { [weak self] in
             guard let self else { return }
             UIView.animate(withDuration: 0.3) { [weak self] in
@@ -70,6 +71,7 @@ extension LNToastView {
         
         textLabel.font = .body_m
         textLabel.textColor = .text_1
+        textLabel.numberOfLines = 0
         addSubview(textLabel)
         textLabel.snp.makeConstraints { make in
             make.center.equalToSuperview()

+ 4 - 0
Lanu/Lanu.entitlements

@@ -2,6 +2,10 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+	<key>com.apple.developer.applesignin</key>
+	<array>
+		<string>Default</string>
+	</array>
 	<key>com.apple.developer.associated-domains</key>
 	<array>
 		<string>applinks:test-web.gami.vip</string>

+ 26 - 3
Lanu/Localizable.xcstrings

@@ -1640,19 +1640,19 @@
         "en" : {
           "stringUnit" : {
             "state" : "translated",
-            "value" : "The playmate has declined the order. Please place your order here or choose another playmate"
+            "value" : "The playmate has declined your order. Please place a new order or select another playmate."
           }
         },
         "id" : {
           "stringUnit" : {
             "state" : "translated",
-            "value" : "Teman bermain telah menolak pesanan. Silakan pesan di sini atau pilih teman bermain lain"
+            "value" : "Pemain Pendamping telah menolak pesananmu. Silakan buat pesanan baru atau pilih pemain pendamping lain."
           }
         },
         "zh-Hans" : {
           "stringUnit" : {
             "state" : "translated",
-            "value" : "陪玩师已拒绝订单,请在此重新下单或选择其他陪玩师"
+            "value" : "陪玩师已拒绝订单,请再次重新下单或选择其他陪玩师"
           }
         }
       }
@@ -6509,6 +6509,29 @@
           }
         }
       }
+    },
+    "A00285" : {
+      "extractionState" : "manual",
+      "localizations" : {
+        "en" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Apple ID login"
+          }
+        },
+        "id" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Login Apple"
+          }
+        },
+        "zh-Hans" : {
+          "stringUnit" : {
+            "state" : "translated",
+            "value" : "Apple 登录"
+          }
+        }
+      }
     }
   },
   "version" : "1.1"

+ 18 - 1
Lanu/Manager/Account/LNAccountManager.swift

@@ -75,7 +75,24 @@ class LNAccountManager {
     }
     
     func loginByGoogle(data: String, completion: ((Bool) -> Void)? = nil) {
-        LNHttpManager.shared.loginByGoogle(data: data) { [weak self] response, err in
+        LNHttpManager.shared.loginByGoogle(token: data) { [weak self] response, err in
+            guard let self else { return }
+            guard err == nil, let response else {
+                showToast(err?.errorDesc)
+                completion?(false)
+                self.clean()
+                return
+            }
+            self.token = response.token
+            self.uid = response.userProfile.userNo
+            completion?(true)
+            
+            self.notifyUserLogin()
+        }
+    }
+    
+    func loginByApple(data: String, completion: ((Bool) -> Void)? = nil) {
+        LNHttpManager.shared.loginByApple(token: data) { [weak self] response, err in
             guard let self else { return }
             guard err == nil, let response else {
                 showToast(err?.errorDesc)

+ 7 - 2
Lanu/Manager/Account/Network/LNHttpManager+Login.swift

@@ -10,14 +10,19 @@ import Foundation
 
 private let kNetPath_Login_Google = "/user/login/google/enter"
 private let kNetPath_Login_Email = "/user/login/email/enter"
+private let kNetPath_Login_Apple = "/user/login/apple/enter"
 
 private let kNetPath_Login_Refresh = "/user/renewalToken"
 
 private let kNetPath_Logout = "/user/logout"
 
 extension LNHttpManager {
-    func loginByGoogle(data: String, completion: @escaping (LNLoginResponse?, LNHttpError?) -> Void) {
-        post(path: kNetPath_Login_Google, params: ["data": data], completion: completion)
+    func loginByGoogle(token: String, completion: @escaping (LNLoginResponse?, LNHttpError?) -> Void) {
+        post(path: kNetPath_Login_Google, params: ["data": token], completion: completion)
+    }
+    
+    func loginByApple(token: String, completion: @escaping (LNLoginResponse?, LNHttpError?) -> Void) {
+        post(path: kNetPath_Login_Apple, params: ["data": token], completion: completion)
     }
     
 #if DEBUG

+ 63 - 9
Lanu/Views/Login/LNLoginPanel.swift

@@ -44,6 +44,22 @@ extension LNLoginPanel: LNAccountManagerNotify {
     }
 }
 
+extension LNLoginPanel: ASAuthorizationControllerDelegate {
+    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
+        guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential,
+              let token = credential.identityToken,
+              let tokenStr = String(data: token, encoding: .utf8)
+        else {
+            return
+        }
+        
+        LNAccountManager.shared.loginByApple(data: tokenStr)
+    }
+    
+    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: any Error) {
+    }
+}
+
 extension LNLoginPanel {
     private func setupViews() {
         container.backgroundColor = .text_5.withAlphaComponent(0.7)
@@ -69,22 +85,20 @@ extension LNLoginPanel {
         stackView.spacing = 16
         container.addSubview(stackView)
         stackView.snp.makeConstraints { make in
-            make.directionalHorizontalEdges.equalToSuperview().inset(38)
+            make.horizontalEdges.equalToSuperview().inset(38)
             make.bottom.equalTo(privacy.snp.top).offset(-50)
         }
         
-        var logins: [UIView] = []
 #if DEBUG
         let email = buildEmail()
-        logins.append(email)
+        stackView.addArrangedSubview(email)
 #endif
         
-        let google = buildGoogleLogin()
-        logins.append(google)
+        let apple = buildAppleLogin()
+        stackView.addArrangedSubview(apple)
         
-        logins.forEach {
-            stackView.addArrangedSubview($0)
-        }
+        let google = buildGoogleLogin()
+        stackView.addArrangedSubview(google)
         
         let tipsLabel = UILabel()
         tipsLabel.text = .init(key: "A00114")
@@ -94,7 +108,7 @@ extension LNLoginPanel {
         tipsLabel.textAlignment = .center
         container.addSubview(tipsLabel)
         tipsLabel.snp.makeConstraints { make in
-            make.directionalHorizontalEdges.equalToSuperview().inset(38)
+            make.horizontalEdges.equalToSuperview().inset(38)
             make.bottom.equalTo(stackView.snp.top).offset(-16)
         }
         
@@ -106,6 +120,45 @@ extension LNLoginPanel {
         }
     }
     
+    private func buildAppleLogin() -> UIView {
+        let button = UIButton()
+        button.backgroundColor = .init(hex: "#0B0B0A")
+        button.layer.cornerRadius = 24
+        button.snp.makeConstraints { make in
+            make.height.equalTo(48)
+        }
+        
+        let ic = UIImageView()
+        ic.image = .init(named: "ic_apple")
+        button.addSubview(ic)
+        ic.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.leading.equalToSuperview().offset(12)
+        }
+        
+        let title = UILabel()
+        title.font = .heading_h3
+        title.textColor = .text_1
+        title.text = .init(key: "A00285")
+        button.addSubview(title)
+        title.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+        
+        button.addAction(UIAction(handler: { [weak self] _ in
+            guard let self else { return }
+            let provider = ASAuthorizationAppleIDProvider()
+            let request = provider.createRequest()
+            request.requestedScopes = [.fullName, .email]
+            let controller = ASAuthorizationController(authorizationRequests: [request])
+            controller.delegate = self
+//            controller.presentationContextProvider = self
+            controller.performRequests()
+        }), for: .touchUpInside)
+        
+        return button
+    }
+    
     private func buildGoogleLogin() -> UIView {
         let button = UIButton()
         button.backgroundColor = .fill
@@ -220,6 +273,7 @@ extension LNLoginPanel {
 #if DEBUG
 
 import SwiftUI
+import AuthenticationServices
 
 struct LNLoginPanelPreview: UIViewRepresentable {
     func makeUIView(context: Context) -> some UIView {

+ 1 - 1
ThirdParty/TUIKit/TUIChat/Resources/TUIChatFace.bundle/Localizable/zh-Hans.lproj/Localizable.strings

@@ -3,7 +3,7 @@
 "[TUIEmoji_Blink]" = "[眨眼]";
 "[TUIEmoji_Guffaw]" = "[大笑]";
 "[TUIEmoji_KindSmile]" = "[姨母笑]";
-"[TUIEmoji_Haha]" = "[[哈哈哈]";
+"[TUIEmoji_Haha]" = "[哈哈哈]";
 "[TUIEmoji_Cheerful]" = "[愉快]";
 "[TUIEmoji_Speechless]" = "[无语]";
 "[TUIEmoji_Amazed]" = "[惊讶]";