Explorar o código

fix: 修复部分 bugs

陈文艺 hai 3 meses
pai
achega
d94ec68d71
Modificáronse 31 ficheiros con 211 adicións e 131 borrados
  1. 2 2
      Lanu.xcodeproj/project.pbxproj
  2. 18 8
      Lanu/Manager/LNDelayTask.swift
  3. 12 0
      Lanu/Manager/Order/LNCommonAlertView+Order.swift
  4. 8 4
      Lanu/Manager/Order/LNOrderManager.swift
  5. 19 21
      Lanu/Manager/Purchase/LNPurchaseManager.swift
  6. 10 0
      Lanu/Manager/Purchase/Network/LNHttpManager+Purchase.swift
  7. 5 0
      Lanu/Manager/Purchase/Network/LNPurchaseResponse.swift
  8. 1 1
      Lanu/Views/IM/Chat/Cells/LNIMChatOrderMessageCell.swift
  9. 8 10
      Lanu/Views/IM/Chat/ViewModel/LNIMChatViewModel.swift
  10. 1 2
      Lanu/Views/Order/Create/LNCreateOrderPanel.swift
  11. 2 3
      Lanu/Views/Order/Create/LNCreateOrderViewController.swift
  12. 15 17
      Lanu/Views/Order/Detail/LNOrderDetailViewController.swift
  13. 9 1
      Lanu/Views/Order/Detail/LNOrderRefundInfoView.swift
  14. 1 1
      Lanu/Views/Order/LNOrderCommentPanel.swift
  15. 1 1
      Lanu/Views/Order/OrderList/LNOrderListItemCell.swift
  16. 3 3
      Lanu/Views/Order/OrderQR/LNOrderQRCodeShowView.swift
  17. 2 0
      Lanu/Views/Order/OrderQR/LNOrderShareImageGenerator.swift
  18. 5 0
      Lanu/Views/Order/OrderRecords/LNOrderRecordCell.swift
  19. 1 1
      Lanu/Views/Order/Refund/LNOrderProtestViewController.swift
  20. 1 1
      Lanu/Views/Order/Refund/LNOrderRefundViewController.swift
  21. 1 1
      Lanu/Views/Profile/Edit/LNEditNickNamePanel.swift
  22. 1 2
      Lanu/Views/Profile/Post/LNPostShareImageGenerator.swift
  23. 2 0
      Lanu/Views/Profile/Profile/LNProfileTabView.swift
  24. 9 10
      Lanu/Views/Profile/Profile/LNProfileViewController.swift
  25. 4 5
      Lanu/Views/Settings/LNSettingsViewController.swift
  26. 33 16
      Lanu/Views/Wallet/Coin/LNCoinToDiamondPanel.swift
  27. 0 4
      Lanu/Views/Wallet/Coin/LNCoinViewController.swift
  28. 34 13
      Lanu/Views/Wallet/Diamond/LNDiamondToCoinPanel.swift
  29. 0 4
      Lanu/Views/Wallet/Diamond/LNDiamondViewController.swift
  30. 1 0
      Lanu/Views/Wallet/LNWalletViewController.swift
  31. 2 0
      Lanu/Views/Web/LNWebViewController.swift

+ 2 - 2
Lanu.xcodeproj/project.pbxproj

@@ -530,7 +530,7 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Lanu/Lanu.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 14;
+				CURRENT_PROJECT_VERSION = 15;
 				DEVELOPMENT_TEAM = 5H8D98R72W;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;
@@ -574,7 +574,7 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Lanu/Lanu.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 14;
+				CURRENT_PROJECT_VERSION = 15;
 				DEVELOPMENT_TEAM = 5H8D98R72W;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;

+ 18 - 8
Lanu/Manager/LNDelayTask.swift

@@ -9,10 +9,8 @@ import Foundation
 
 class LNDelayTask {
     // 保存任务实例,用于取消
-    private static var workItems = NSMapTable<NSString, DispatchWorkItem>.init(
-        keyOptions: .strongMemory,
-        valueOptions: .weakMemory
-    )
+    private static let lock = NSLock()
+    private static var workItems: [String: DispatchWorkItem] = [:]
     
     /// 执行延时任务(可取消)
     /// - Parameters:
@@ -22,9 +20,17 @@ class LNDelayTask {
     @discardableResult
     static func perform(delay: TimeInterval, queue: DispatchQueue = .main, task: @escaping () -> Void) -> String {
         // 创建任务
-        let workItem = DispatchWorkItem(block: task)
         let uuid = UUID().uuidString
-        workItems.setObject(workItem, forKey: uuid as NSString)
+        let workItem = DispatchWorkItem(block: {
+            lock.lock()
+            workItems.removeValue(forKey: uuid)
+            lock.unlock()
+            
+            task()
+        })
+        lock.lock()
+        workItems[uuid] = workItem
+        lock.unlock()
         
         // 延时执行
         queue.asyncAfter(deadline: .now() + delay, execute: workItem)
@@ -35,10 +41,14 @@ class LNDelayTask {
     /// 取消延时任务
     static func cancel(key: String?) {
         guard let key else { return }
-        guard let task = workItems.object(forKey: key as NSString) else {
+        
+        lock.lock()
+        defer {
+            lock.unlock()
+        }
+        guard let task = workItems.removeValue(forKey: key) else {
             return
         }
-        workItems.removeObject(forKey: key as NSString)
         
         task.cancel()
     }

+ 12 - 0
Lanu/Manager/Order/LNCommonAlertView+Order.swift

@@ -20,4 +20,16 @@ extension LNCommonAlertView {
         }
         panel.popup()
     }
+    
+    static func showFinishOrderAlert(orderId: String, completion: ((Bool) -> Void)? = nil) {
+        let panel = LNCommonAlertView()
+        panel.titleLabel.text = .init(key: "确认完成订单吗?")
+        panel.setConfirm(.init(key: "确定完成")) {
+            LNOrderManager.shared.finishOrder(orderId: orderId) { success in
+                completion?(success)
+            }
+        }
+        panel.setCancel(.init(key: "取消")) { }
+        panel.popup()
+    }
 }

+ 8 - 4
Lanu/Manager/Order/LNOrderManager.swift

@@ -12,17 +12,21 @@ protocol LNOrderManagerNotify {
     func onOrderInfoChanged(orderId: String)
 }
 
+enum LNOrderErrorCode: Int {
+    case NotEnoughMoney = 100010
+}
+
 
 class LNOrderManager {
     static var shared = LNOrderManager()
+    static let orderExtraMaxLength = 150
+    static let orderProtestMaxLength = 500
+    static let orderRefundMaxLength = 500
+    static let orderCommentMaxLength = 200
     
     private init() {}
 }
 
-enum LNOrderErrorCode: Int {
-    case NotEnoughMoney = 100010
-}
-
 
 // MARK: 订单信息
 extension LNOrderManager {

+ 19 - 21
Lanu/Manager/Purchase/LNPurchaseManager.swift

@@ -126,7 +126,9 @@ extension LNPurchaseManager {
             queue.asyncIfNotGlobal {
                 handler(err == nil)
             }
-            if err == nil {
+            if let err {
+                showToast(err.errorDescription)
+            } else {
                 reloadWalletInfo()
             }
         }
@@ -141,7 +143,9 @@ extension LNPurchaseManager {
             queue.asyncIfNotGlobal {
                 handler(err == nil)
             }
-            if err == nil {
+            if let err {
+                showToast(err.errorDescription)
+            } else {
                 reloadWalletInfo()
             }
         }
@@ -158,17 +162,22 @@ extension LNPurchaseManager {
             exchangeConfig = config
         }
     }
+    
+    func expectResult(from: LNCurrencyType, to: LNCurrencyType,
+                      count: Double, queue: DispatchQueue = .main,
+                      handler: @escaping (Double?) -> Void) {
+        LNHttpManager.shared.getExchangeExpectResult(from: from, to: to, count: count) { res, err in
+            queue.asyncIfNotGlobal {
+                handler(res?.amount)
+            }
+            if let err {
+                showToast(err.errorDescription)
+            }
+        }
+    }
 }
 
 extension LNPurchaseManager {
-    var coinToDiamondRatio: Decimal? {
-        guard let exchangeConfig else {
-            getExchangeConfig()
-            return nil
-        }
-        return Decimal(exchangeConfig.diamond / exchangeConfig.coin)
-    }
-    
     var coinToCash: Decimal? {
         guard let exchangeConfig else {
             getExchangeConfig()
@@ -176,14 +185,6 @@ extension LNPurchaseManager {
         }
         return Decimal(exchangeConfig.idr / exchangeConfig.coin)
     }
-    
-    var diamondToCoinRatio: Decimal? {
-        guard let exchangeConfig else {
-            getExchangeConfig()
-            return nil
-        }
-        return Decimal(exchangeConfig.coin / exchangeConfig.diamond)
-    }
 }
 
 extension LNPurchaseManager: LNAccountManagerNotify {
@@ -194,9 +195,6 @@ extension LNPurchaseManager: LNAccountManagerNotify {
         loadGoodsList(currencyType: .coin) { _ in }
         loadGoodsList(currencyType: .diamond) { _ in }
         
-        // 拉取转换配置
-        getExchangeConfig()
-        
 //        restoreCompletedTransactions()
 //        startObservingTransactionUpdates()
     }

+ 10 - 0
Lanu/Manager/Purchase/Network/LNHttpManager+Purchase.swift

@@ -17,6 +17,7 @@ private let kNetPath_Purchase_Create = "/wallet/recharge/submit"
 private let kNetPath_Purchase_Verify = "/wallet/recharge/goods/payBak"
 
 private let kNetPath_Purchase_Exchange = "/wallet/exchange"
+private let kNetPath_Purchase_Pre = "/wallet/exchange/pre"
 
 
 extension LNHttpManager {
@@ -54,4 +55,13 @@ extension LNHttpManager {
             "receipt": receipt
         ], completion: completion)
     }
+    
+    func getExchangeExpectResult(from: LNCurrencyType, to: LNCurrencyType, count: Double,
+                                 completion: @escaping (LNExchangeExpectResponse?, LNHttpError?) -> Void) {
+        post(path: kNetPath_Purchase_Pre, params: [
+            "fromWalletType": from.rawValue,
+            "toWalletType": to.rawValue,
+            "amount": count
+        ], completion: completion)
+    }
 }

+ 5 - 0
Lanu/Manager/Purchase/Network/LNPurchaseResponse.swift

@@ -54,3 +54,8 @@ class LNPurchaseGoodsListResponse: Decodable {
 class LNPurchaseCreateOrderResponse: Decodable {
     var result: String = ""
 }
+
+@AutoCodable
+class LNExchangeExpectResponse: Decodable {
+    var amount: Double = 0.0
+}

+ 1 - 1
Lanu/Views/IM/Chat/Cells/LNIMChatOrderMessageCell.swift

@@ -293,7 +293,7 @@ extension LNIMChatOrderMessageCell {
                 }
             case .serviceDone:
                 if isCreator {
-                    LNOrderManager.shared.finishOrder(orderId: order.orderId) { success in }
+                    LNCommonAlertView.showFinishOrderAlert(orderId: order.orderId)
                 }
             default: break
             }

+ 8 - 10
Lanu/Views/IM/Chat/ViewModel/LNIMChatViewModel.swift

@@ -31,7 +31,6 @@ class LNIMChatViewModel: NSObject {
     private var loading = false
     private(set) var allMessage: [LNIMMessageData] = []
     private var lastData: Date? = nil
-    private var lastMessage: V2TIMMessage?
     private var orderMessageCache: [String: LNIMMessageData] = [:]
     
     // 配置
@@ -219,9 +218,16 @@ extension LNIMChatViewModel {
         }
         loading = true
         
+        let topMessage = allMessage.first {
+            if case .system = $0.type {
+                false
+            } else {
+                true
+            }
+        }
         V2TIMManager.sharedInstance().getC2CHistoryMessageList(
             userID: userId, count: 300,
-            lastMsg: lastMessage)
+            lastMsg: topMessage?.imMessage)
         { [weak self] list in
             guard let self else { return }
             
@@ -232,14 +238,6 @@ extension LNIMChatViewModel {
                 return
             }
             
-            if list.count == 1,
-                list[0].msgID == lastMessage?.msgID {
-                loading = false
-                handler(false, isFirst)
-                return
-            }
-            
-            lastMessage = list.last
             let messages = transUIMsgFromIMMsg(messages: list)
             
             allMessage.insert(contentsOf: messages, at: 0)

+ 1 - 2
Lanu/Views/Order/Create/LNCreateOrderPanel.swift

@@ -25,7 +25,6 @@ class LNCreateOrderPanel: LNPopupView {
     private let countLabel = UILabel()
     private let costLabel = UILabel()
     
-    private let maxInput = 50
     private let extraView = UIView()
     private let extraInput = UITextField()
     
@@ -120,7 +119,7 @@ extension LNCreateOrderPanel: UITextFieldDelegate {
         guard let range = Range(range, in: currentText) else { return false }
         let newText = currentText.replacingCharacters(in: range, with: string)
         
-        return newText.utf8.count <= maxInput
+        return newText.count <= LNOrderManager.orderExtraMaxLength
     }
 }
 

+ 2 - 3
Lanu/Views/Order/Create/LNCreateOrderViewController.swift

@@ -53,7 +53,6 @@ class LNCreateOrderViewController: LNViewController {
         }
     }
     
-    private let maxInput = 50
     private let extraInput = UITextField()
     
     private let costLabel = UILabel()
@@ -83,7 +82,7 @@ extension LNCreateOrderViewController: UITextFieldDelegate {
         guard let range = Range(range, in: currentText) else { return false }
         let newText = currentText.replacingCharacters(in: range, with: string)
         
-        return newText.utf8.count <= maxInput
+        return newText.count <= LNOrderManager.orderExtraMaxLength
     }
 }
 
@@ -429,7 +428,7 @@ extension LNCreateOrderViewController {
         
         extraInput.font = .body_s
         extraInput.textColor = .text_5
-        extraInput.placeholder = .init(key: "填写额外对大神的要求,最多%d字", maxInput)
+        extraInput.placeholder = .init(key: "填写额外对大神的要求,最多%d字", LNOrderManager.orderExtraMaxLength)
         extraInput.clearButtonMode = .whileEditing
         extraInput.delegate = self
         container.addSubview(extraInput)

+ 15 - 17
Lanu/Views/Order/Detail/LNOrderDetailViewController.swift

@@ -282,9 +282,11 @@ extension LNOrderDetailViewController {
     }
     
     private func buildBottomMenu() -> UIView {
-        let container = UIView()
-        container.snp.makeConstraints { make in
-            make.height.equalTo(47)
+        let stackView = UIStackView()
+        stackView.axis = .vertical
+        stackView.spacing = 0
+        stackView.snp.makeConstraints { make in
+            make.height.equalTo(0).priority(.low)
         }
         
         cancelButton.isHidden = true
@@ -298,10 +300,9 @@ extension LNOrderDetailViewController {
             guard let self else { return }
             LNCommonAlertView.showCancelOrderAlert(orderId: orderId)
         }), for: .touchUpInside)
-        container.addSubview(cancelButton)
+        stackView.addArrangedSubview(cancelButton)
         cancelButton.snp.makeConstraints { make in
-            make.directionalHorizontalEdges.equalToSuperview().inset(16)
-            make.verticalEdges.equalToSuperview()
+            make.height.equalTo(47)
         }
         
         refundButton.isHidden = true
@@ -315,10 +316,9 @@ extension LNOrderDetailViewController {
             guard let self else { return }
             view.pushToOrderRefund(orderId)
         }), for: .touchUpInside)
-        container.addSubview(refundButton)
+        stackView.addArrangedSubview(refundButton)
         refundButton.snp.makeConstraints { make in
-            make.directionalHorizontalEdges.equalToSuperview().inset(16)
-            make.verticalEdges.equalToSuperview()
+            make.height.equalTo(47)
         }
         
         let cover = UIView()
@@ -344,17 +344,15 @@ extension LNOrderDetailViewController {
             panel.update(curDetail.orderInfo.avatar, orderId: orderId)
             panel.showIn()
         }), for: .touchUpInside)
-        container.addSubview(commentButton)
+        stackView.addArrangedSubview(commentButton)
         commentButton.snp.makeConstraints { make in
-            make.directionalHorizontalEdges.equalToSuperview().inset(16)
-            make.verticalEdges.equalToSuperview()
+            make.height.equalTo(47)
         }
         
         completeView.isHidden = true
-        container.addSubview(completeView)
+        stackView.addArrangedSubview(completeView)
         completeView.snp.makeConstraints { make in
-            make.directionalHorizontalEdges.equalToSuperview().inset(16)
-            make.verticalEdges.equalToSuperview()
+            make.height.equalTo(47)
         }
         let refundButton = UIButton()
         refundButton.layer.cornerRadius = 23.5
@@ -384,7 +382,7 @@ extension LNOrderDetailViewController {
         completeButton.clipsToBounds = true
         completeButton.addAction(UIAction(handler: { [weak self] _ in
             guard let self else { return }
-            LNOrderManager.shared.finishOrder(orderId: orderId) { _ in }
+            LNCommonAlertView.showFinishOrderAlert(orderId: orderId, completion: nil)
         }), for: .touchUpInside)
         completeView.addSubview(completeButton)
         completeButton.snp.makeConstraints { make in
@@ -393,7 +391,7 @@ extension LNOrderDetailViewController {
             make.trailing.equalToSuperview()
         }
         
-        return container
+        return stackView
     }
 }
 

+ 9 - 1
Lanu/Views/Order/Detail/LNOrderRefundInfoView.swift

@@ -24,10 +24,18 @@ class LNOrderRefundInfoView: UIView {
         isHidden =  detail.reason.isEmpty 
         reasonLabel.text = detail.reason
         var photos: [UIImageView] = []
-        for attachment in detail.attachments {
+        for (index, attachment) in detail.attachments.enumerated() {
             let imageView = UIImageView()
+            imageView.isUserInteractionEnabled = true
             imageView.sd_setImage(with: URL(string: attachment.attachmentUrl))
             photos.append(imageView)
+            imageView.snp.makeConstraints { make in
+                make.width.height.equalTo(100)
+            }
+            imageView.onTap { [weak self] in
+                guard let self else { return }
+                presentImagePreview(detail.attachments.map({ $0.attachmentUrl }), index)
+            }
         }
         photosView.update(photos)
     }

+ 1 - 1
Lanu/Views/Order/LNOrderCommentPanel.swift

@@ -105,7 +105,7 @@ extension LNOrderCommentPanel {
             make.leading.greaterThanOrEqualTo(scoreView.snp.leading).offset(12)
         }
         
-        commentView.maxInput = 200
+        commentView.maxInput = LNOrderManager.orderCommentMaxLength
         commentView.placeholderLabel.text = .init(key: "展开说说对Ta的看法吧...")
         container.addSubview(commentView)
         commentView.snp.makeConstraints { make in

+ 1 - 1
Lanu/Views/Order/OrderList/LNOrderListItemCell.swift

@@ -76,7 +76,7 @@ extension LNOrderListItemCell {
             panel.showIn()
             break
         case .serviceDone: // 可以点击完成
-            LNOrderManager.shared.finishOrder(orderId: orderItem.orderId) { [weak self] success in
+            LNCommonAlertView.showFinishOrderAlert(orderId: orderItem.orderId) { [weak self] success in
                 guard let self else { return }
                 guard success else { return }
                 orderItem.status = .completed

+ 3 - 3
Lanu/Views/Order/OrderQR/LNOrderQRCodeShowView.swift

@@ -19,7 +19,7 @@ class LNOrderQRCodeShowView: UIView {
     private let saveButton = UIButton()
     private let copyButton = UIButton()
     
-    private var qrCodeData: String?
+    private var qrCodeUrl: String?
     
     private var curSkill: LNGameMateSkillVO?
     private var count: Int = 0
@@ -67,7 +67,7 @@ class LNOrderQRCodeShowView: UIView {
                       self.count == count else { return }
                 let url: String = .orderQRShareUrl + "?id=\(skill.id)&code=\(qrCode)"
                 self.qrCodeIc.image = url.toQRCode(size: qrCodeSize)
-                self.qrCodeData = qrCode
+                self.qrCodeUrl = url
                 self.saveButton.isEnabled = true
                 self.copyButton.isEnabled = true
             }
@@ -165,7 +165,7 @@ extension LNOrderQRCodeShowView {
         copyButton.titleLabel?.font = .heading_h3
         copyButton.addAction(UIAction(handler: { [weak self] _ in
             guard let self else { return }
-            UIPasteboard.general.string = self.qrCodeData
+            UIPasteboard.general.string = self.qrCodeUrl
             showToast(.init(key: "已复制到剪切板"))
         }), for: .touchUpInside)
         addSubview(copyButton)

+ 2 - 0
Lanu/Views/Order/OrderQR/LNOrderShareImageGenerator.swift

@@ -28,6 +28,7 @@ class LNOrderShareImageGenerator {
     }
     
     func update(skill: LNGameMateSkillVO, count: Int, image: UIImage) {
+        avatar.sd_setImage(with: URL(string: myUserInfo.avatar))
         skillIc.sd_setImage(with: URL(string: skill.icon))
         skillNameLabel.text = skill.name
         scoreView.score = myGameMateInfo?.star ?? 0
@@ -76,6 +77,7 @@ extension LNOrderShareImageGenerator {
         avatar.layer.cornerRadius = 37.5
         avatar.layer.borderWidth = 2
         avatar.layer.borderColor = UIColor.fill.cgColor
+        avatar.clipsToBounds = true
         avatar.sd_setImage(with: URL(string: myUserInfo.avatar))
         container.addSubview(avatar)
         avatar.snp.makeConstraints { make in

+ 5 - 0
Lanu/Views/Order/OrderRecords/LNOrderRecordCell.swift

@@ -329,6 +329,7 @@ extension LNOrderRecordCell {
                 guard let self else { return }
                 guard success else { return }
                 curItem.status = .rejected
+                updateByStateChanged()
             }
         }), for: .touchUpInside)
         rejectButton.snp.makeConstraints { make in
@@ -350,6 +351,7 @@ extension LNOrderRecordCell {
                 guard let self else { return }
                 guard success else { return }
                 curItem.status = .accepted
+                updateByStateChanged()
             }
         }), for: .touchUpInside)
         acceptButton.snp.makeConstraints { make in
@@ -371,6 +373,7 @@ extension LNOrderRecordCell {
                 guard let self else { return }
                 guard success else { return }
                 curItem.status = .servicing
+                updateByStateChanged()
             }
         }), for: .touchUpInside)
         startButton.snp.makeConstraints { make in
@@ -392,6 +395,7 @@ extension LNOrderRecordCell {
                 guard let self else { return }
                 guard success else { return }
                 curItem.status = .serviceDone
+                updateByStateChanged()
             }
         }), for: .touchUpInside)
         completeButton.snp.makeConstraints { make in
@@ -412,6 +416,7 @@ extension LNOrderRecordCell {
             pushToProtest(curItem.orderId) { [weak self] in
                 guard let self else { return }
                 curItem.status = .serviceDone
+                updateByStateChanged()
             }
         }), for: .touchUpInside)
         commitButton.snp.makeConstraints { make in

+ 1 - 1
Lanu/Views/Order/Refund/LNOrderProtestViewController.swift

@@ -405,7 +405,7 @@ extension LNOrderProtestViewController {
         }
         
         messageInputView.delegate = self
-        messageInputView.maxInput = 500
+        messageInputView.maxInput = LNOrderManager.orderProtestMaxLength
         container.addSubview(messageInputView)
         messageInputView.snp.makeConstraints { make in
             make.directionalHorizontalEdges.equalToSuperview().inset(16)

+ 1 - 1
Lanu/Views/Order/Refund/LNOrderRefundViewController.swift

@@ -206,7 +206,7 @@ extension LNOrderRefundViewController {
         }
         
         messageInputView.delegate = self
-        messageInputView.maxInput = 500
+        messageInputView.maxInput = LNOrderManager.orderRefundMaxLength
         container.addSubview(messageInputView)
         messageInputView.snp.makeConstraints { make in
             make.directionalHorizontalEdges.equalToSuperview().inset(16)

+ 1 - 1
Lanu/Views/Profile/Edit/LNEditNickNamePanel.swift

@@ -36,7 +36,7 @@ extension LNEditNickNamePanel: UITextFieldDelegate {
         guard let range = Range(range, in: currentText) else { return false }
         let newText = currentText.replacingCharacters(in: range, with: string)
         
-        return newText.utf8.count <= maxInput
+        return newText.count <= maxInput
     }
 }
 

+ 1 - 2
Lanu/Views/Profile/Post/LNPostShareImageGenerator.swift

@@ -42,8 +42,7 @@ class LNPostShareImageGenerator {
     }
     
     func setOrderInfo(desc: String?) {
-        newsLabel.text = desc
-        newsView.isHidden = desc?.isEmpty != false
+        newsLabel.text = desc?.isEmpty != false ? desc : .init(key: "快来和我玩吧")
     }
     
     func setSkills(skills: [LNGameMateSkillVO]) {

+ 2 - 0
Lanu/Views/Profile/Profile/LNProfileTabView.swift

@@ -82,6 +82,7 @@ extension LNProfileTabView {
         infoTab.setTitleColor(.text_5, for: .selected)
         infoTab.setTitleColor(.text_3, for: .normal)
         infoTab.setTitle(.init(key: "About Her"), for: .normal)
+        infoTab.titleLabel?.font = .heading_h4
         infoTab.addAction(UIAction(handler: { [weak self] _ in
             guard let self else { return }
             self.curSelected = .info
@@ -94,6 +95,7 @@ extension LNProfileTabView {
         photoTab.setTitleColor(.text_5, for: .selected)
         photoTab.setTitleColor(.text_3, for: .normal)
         photoTab.setTitle(.init(key: "Photo Wall"), for: .normal)
+        photoTab.titleLabel?.font = .heading_h4
         photoTab.addAction(UIAction(handler: { [weak self] _ in
             guard let self else { return }
             self.curSelected = .photo

+ 9 - 10
Lanu/Views/Profile/Profile/LNProfileViewController.swift

@@ -61,11 +61,9 @@ class LNProfileViewController: LNViewController {
         
         infoView.maxHeight = scrollView.bounds.height
         - CGRectGetHeight(fakeNavBar.bounds)
-        - (uid.isMyUid ? 0 : (view.safeBottomInset + 30))
         
         infoView.minHeight = scrollView.bounds.height
-        - cover.bounds.height + 52
-        - (uid.isMyUid ? 0 : (view.safeBottomInset + 30))
+        - cover.bounds.height + 52 - scrollView.contentInset.bottom
     }
     
     required init?(coder: NSCoder) {
@@ -76,9 +74,13 @@ class LNProfileViewController: LNViewController {
 extension LNProfileViewController: UIScrollViewDelegate {
     func scrollViewDidScroll(_ scrollView: UIScrollView) {
         let offset = CGRectGetMinY(infoView.frame) - CGRectGetHeight(fakeNavBar.bounds)
+        let min = offset - UIView.statusBarHeight
         
-        let distance = min(scrollView.contentOffset.y, offset)
-        let progress = distance / offset
+        let progress: Double = if scrollView.contentOffset.y < min {
+            0.0
+        } else {
+            (scrollView.contentOffset.y - min) / UIView.statusBarHeight
+        }
         fakeNavBar.updateProgress(progress)
         infoView.progress = progress
     }
@@ -115,6 +117,7 @@ extension LNProfileViewController {
         scrollView.showsHorizontalScrollIndicator = false
         scrollView.backgroundColor = .fill
         scrollView.delegate = self
+        scrollView.contentInset = .init(top: 0, left: 0, bottom: 80, right: 0)
         view.addSubview(scrollView)
         scrollView.snp.makeConstraints { make in
             make.directionalHorizontalEdges.equalToSuperview()
@@ -143,11 +146,7 @@ extension LNProfileViewController {
         gameView.snp.makeConstraints { make in
             make.directionalHorizontalEdges.equalToSuperview()
             make.top.equalTo(cover.snp.bottom).offset(-52)
-            if uid.isMyUid {
-                make.bottom.equalToSuperview()
-            } else {
-                make.bottom.equalToSuperview().offset(-view.safeBottomInset - 30)
-            }
+            make.bottom.equalToSuperview()
         }
         
         let userInfoView = buildUserInfoView()

+ 4 - 5
Lanu/Views/Settings/LNSettingsViewController.swift

@@ -20,7 +20,6 @@ extension UIView {
 
 class LNSettingsViewController: LNViewController {
     private let curLanguageLabel = UILabel()
-    private let cacheCountLabel = UILabel()
     
     override func viewDidLoad() {
         super.viewDidLoad()
@@ -61,10 +60,10 @@ extension LNSettingsViewController {
         }
         stackView.addArrangedSubview(language)
         
-        let cleanCache = buildFunctionItem(icName: "ic_clean_cache", title: .init(key: "清理缓存"), infoView: cacheCountLabel)
-        cacheCountLabel.font = .body_s
-        cacheCountLabel.textColor = .text_5
-        cacheCountLabel.text = "100MB"
+        let cleanCache = buildFunctionItem(icName: "ic_clean_cache", title: .init(key: "清理缓存"), infoView: nil)
+        cleanCache.onTap {
+            showToast(.init(key: "缓存已清理"))
+        }
         stackView.addArrangedSubview(cleanCache)
         
         let newVersionTag = LNNewVersionView()

+ 33 - 16
Lanu/Views/Wallet/Coin/LNCoinToDiamondPanel.swift

@@ -16,7 +16,7 @@ class LNCoinToDiamondPanel: LNPopupView {
     private let diamondLabel = UILabel()
     
     private let exchangeButton = UIButton()
-    private let exchangeRatio = LNPurchaseManager.shared.coinToDiamondRatio ?? 1
+    private var delayTaskId: String?
     
     override init(frame: CGRect) {
         super.init(frame: frame)
@@ -39,22 +39,39 @@ extension LNCoinToDiamondPanel {
         } else {
             coinInput.attributedPlaceholder = nil
         }
-        
-        let value = Int(text) ?? 0
-        if value > 0 {
-            if !exchangeButton.isEnabled {
-                exchangeButton.isEnabled = true
-                exchangeButton.setBackgroundImage(.primary_8, for: .normal)
+        let value = Double(text) ?? 0
+        if value > 0, !exchangeButton.isEnabled {
+            exchangeButton.isEnabled = true
+            exchangeButton.setBackgroundImage(.primary_8, for: .normal)
+        } else if value <= 0, exchangeButton.isEnabled {
+            exchangeButton.isEnabled = false
+            exchangeButton.setBackgroundImage(nil, for: .normal)
+        }
+        fetchExchangeResult()
+    }
+    
+    private func fetchExchangeResult() {
+        LNDelayTask.cancel(key: delayTaskId)
+        delayTaskId = LNDelayTask.perform(delay: 1.5) { [weak self] in
+            guard let self else { return }
+            let text = coinInput.text ?? ""
+            let value = Double(text) ?? 0
+            if value == 0 {
+                diamondLabel.text = "0"
+                return
             }
-            
-            diamondLabel.text = "\(exchangeRatio * Decimal(value))"
-        } else if value <= 0 {
-            if exchangeButton.isEnabled {
-                exchangeButton.isEnabled = false
-                exchangeButton.setBackgroundImage(nil, for: .normal)
+            LNPurchaseManager.shared.expectResult(
+                from: .coin, to: .diamond, count: value)
+            { [weak self] result in
+                guard let self else { return }
+                guard coinInput.text == text else { return }
+                
+                if let result {
+                    diamondLabel.text = "\(result)"
+                } else {
+                    diamondLabel.text = ""
+                }
             }
-            
-            diamondLabel.text = "0"
         }
     }
     
@@ -105,7 +122,7 @@ extension LNCoinToDiamondPanel {
             make.top.equalTo(line.snp.bottom).offset(4)
         }
         
-        exchangeButton.setTitle(.init(key: "With Draw"), for: .normal)
+        exchangeButton.setTitle(.init(key: "Confirm Exchange"), for: .normal)
         exchangeButton.setTitleColor(.text_1, for: .normal)
         exchangeButton.titleLabel?.font = .heading_h3
         exchangeButton.setBackgroundImage(.primary_8, for: .normal)

+ 0 - 4
Lanu/Views/Wallet/Coin/LNCoinViewController.swift

@@ -33,9 +33,6 @@ class LNCoinViewController: LNViewController {
         rechargeView.loadList(.coin)
         onUserWalletInfoChanged(info: myWalletInfo)
         
-        // 获取转换比例,如果没有,触发更新
-        _ = LNPurchaseManager.shared.coinToDiamondRatio
-        
         LNEventDeliver.addObserver(self)
     }
 }
@@ -131,7 +128,6 @@ extension LNCoinViewController {
         
         let jumpButton = UIButton()
         jumpButton.addAction(UIAction(handler: { _ in
-            guard LNPurchaseManager.shared.coinToDiamondRatio != nil else { return }
             let panel = LNCoinToDiamondPanel()
             panel.showIn()
         }), for: .touchUpInside)

+ 34 - 13
Lanu/Views/Wallet/Diamond/LNDiamondToCoinPanel.swift

@@ -16,7 +16,7 @@ class LNDiamondToCoinPanel: LNPopupView {
     private let coinLabel = UILabel()
     
     private let exchangeButton = UIButton()
-    private let exchangeRatio = LNPurchaseManager.shared.diamondToCoinRatio ?? 1
+    private var delayTaskId: String?
     
     override init(frame: CGRect) {
         super.init(frame: frame)
@@ -40,20 +40,41 @@ extension LNDiamondToCoinPanel {
             diamondInput.attributedPlaceholder = nil
         }
         
-        let value = Int(text) ?? 0
-        let coinValue = exchangeRatio * Decimal(value)
-        if coinValue >= 1.0 {
-            if !exchangeButton.isEnabled {
-                exchangeButton.isEnabled = true
-                exchangeButton.setBackgroundImage(.primary_8, for: .normal)
+        let value = Double(text) ?? 0
+        if value > 0, !exchangeButton.isEnabled {
+            exchangeButton.isEnabled = true
+            exchangeButton.setBackgroundImage(.primary_8, for: .normal)
+        } else if value <= 0, exchangeButton.isEnabled {
+            exchangeButton.isEnabled = false
+            exchangeButton.setBackgroundImage(nil, for: .normal)
+        }
+        
+        fetchExchangeResult()
+    }
+    
+    private func fetchExchangeResult() {
+        LNDelayTask.cancel(key: delayTaskId)
+        delayTaskId = LNDelayTask.perform(delay: 0.5) { [weak self] in
+            guard let self else { return }
+            let text = diamondInput.text ?? ""
+            let value = Double(text) ?? 0
+            if value == 0 {
+                coinLabel.text = "0"
+                return
             }
-        } else {
-            if exchangeButton.isEnabled {
-                exchangeButton.isEnabled = false
-                exchangeButton.setBackgroundImage(nil, for: .normal)
+            LNPurchaseManager.shared.expectResult(
+                from: .diamond, to: .coin, count: value)
+            { [weak self] result in
+                guard let self else { return }
+                guard diamondInput.text == text else { return }
+                
+                if let result {
+                    coinLabel.text = "\(result)"
+                } else {
+                    coinLabel.text = ""
+                }
             }
         }
-        coinLabel.text = "\(coinValue)"
     }
     
     private func setupViews() {
@@ -103,7 +124,7 @@ extension LNDiamondToCoinPanel {
             make.top.equalTo(line.snp.bottom).offset(4)
         }
         
-        exchangeButton.setTitle(.init(key: "With Draw"), for: .normal)
+        exchangeButton.setTitle(.init(key: "Confirm Exchange"), for: .normal)
         exchangeButton.setTitleColor(.text_1, for: .normal)
         exchangeButton.titleLabel?.font = .heading_h3
         exchangeButton.setBackgroundImage(.primary_8, for: .normal)

+ 0 - 4
Lanu/Views/Wallet/Diamond/LNDiamondViewController.swift

@@ -33,9 +33,6 @@ class LNDiamondViewController: LNViewController {
         rechargeView.loadList(.diamond)
         onUserWalletInfoChanged(info: myWalletInfo)
         
-        // 获取转换比例,如果没有,触发更新
-        _ = LNPurchaseManager.shared.diamondToCoinRatio
-        
         LNEventDeliver.addObserver(self)
     }
 }
@@ -131,7 +128,6 @@ extension LNDiamondViewController {
         
         let jumpButton = UIButton()
         jumpButton.addAction(UIAction(handler: { _ in
-            guard LNPurchaseManager.shared.diamondToCoinRatio != nil else { return }
             let panel = LNDiamondToCoinPanel()
             panel.showIn()
         }), for: .touchUpInside)

+ 1 - 0
Lanu/Views/Wallet/LNWalletViewController.swift

@@ -31,6 +31,7 @@ class LNWalletViewController: LNViewController {
         
         updateWalletInfo()
         LNEventDeliver.addObserver(self)
+        LNPurchaseManager.shared.reloadWalletInfo()
     }
 }
 

+ 2 - 0
Lanu/Views/Web/LNWebViewController.swift

@@ -166,6 +166,8 @@ extension LNWebViewController {
             webView.isInspectable = true
         }
 #endif
+        webView.scrollView.contentInsetAdjustmentBehavior = .never
+        webView.scrollView.bounces = false
         
         webView.publisher(for: \.title).removeDuplicates().sink
         { [weak self] webTitle in