| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528 |
- //
- // MOGiftListViewModel.swift
- // MiMoLive
- //
- // Created by OneeChan on 2025/9/18.
- //
- import Foundation
- @objc
- protocol MOGiftListViewModelDelegate {
- @objc optional func onGiftListChanged(category: Int, list: [MOGiftlist])
- @objc optional func onUserBalanceChangedBySendGift(current: Int)
- @objc optional func onUserLevelChangedBySendGift(level: Int, curExp: Int, nextExp: Int)
- @objc optional func onSendGiftSuccess(category: Int, num: Int, gift: MOGiftlist, info: MOGiftInfo)
-
- @objc optional func onSendBagSuccess(category: Int, num: Int, gift: MOGiftlist, info: MOGiftInfo, newItem: MOGiftlist?)
- }
- @objcMembers
- class MOGiftListViewModel: NSObject {
- private static let kPageSize = 60
-
- private let observers: NSHashTable<MOGiftListViewModelDelegate> = NSHashTable.weakObjects()
-
- @objc
- enum GiftCategory: Int {
- case hot = 1
- case lucky = 2
- case fans = 3
- case vip = 4
- case lv = 5
- case funny = 6
- case luxury = 7
- case sl = 8
- }
- private var categories: [MOGiftCategoryList] = [
- MOGiftCategoryList.initWith("Hot", code: Double(GiftCategory.hot.rawValue)),
- MOGiftCategoryList.initWith("SL", code: Double(GiftCategory.sl.rawValue)),
- MOGiftCategoryList.initWith("Lucky", code: Double(GiftCategory.lucky.rawValue)),
- MOGiftCategoryList.initWith("Fans", code: Double(GiftCategory.fans.rawValue)),
- MOGiftCategoryList.initWith("Vip", code: Double(GiftCategory.vip.rawValue)),
- MOGiftCategoryList.initWith("Lv", code: Double(GiftCategory.lv.rawValue)),
- MOGiftCategoryList.initWith("Funny", code: Double(GiftCategory.funny.rawValue)),
- MOGiftCategoryList.initWith("Luxury", code: Double(GiftCategory.luxury.rawValue))
- ]
-
- private var curRoom: MOLiveDetail? = nil
- var curRoomId: String? {
- curRoom?.currentRoom.id
- }
-
- private var giftCache: [Int: [MOGiftlist]] = [:]
- private var giftNextTags: [Int: String] = [:]
-
- override init() {
- super.init()
-
- MOEventDeliver.addObserver(self)
- }
- }
- // MARK: Category 类别
- extension MOGiftListViewModel {
- var categoryTitles: [String] {
- categories.map { $0.name }
- }
-
- func category(at: Int) -> MOGiftCategoryList? {
- guard at < categories.count else { return nil }
- return categories[at]
- }
-
- func checkGiftCategory() {
- let category = MOSvgaSourceManage.shareManager().giftCategoryArr
-
- if category.count == 0 {
- MOSvgaSourceManage.shareManager().toGetGiftCategoryListDataAndNeedShowError(true)
- } else {
- categories = category.compactMap({ item in
- guard let item = item as? MOGiftCategoryList else { return nil }
- return item
- })
- }
- preloadGiftList()
- }
- }
- // MARK: Bag 包裹
- extension MOGiftListViewModel {
- func sendBag(toUid: String, category: Int, gift: MOGiftlist, num: Int, completion: ((Bool) -> Void)? = nil) {
- guard !toUid.isEmpty else {
- MBProgressHUD.showTipMessage(inWindow: NSLocalizedString("mimo_2_live_gift_send_0_tip", comment: ""))
- completion?(false)
- return
- }
- guard let roomId = curRoomId,
- !roomId.isEmpty,
- let giftInfo = gift.giftInfo,
- let giftId = giftInfo.id,
- !giftId.isEmpty,
- let notifyGift = gift.copy() as? MOGiftlist
- else {
- completion?(false)
- return
- }
- let skinCode: Double = if let skin = gift.giftInfo.selectSkin {
- skin.code
- } else {
- 0
- }
- let skin = gift.giftInfo.selectSkin?.copy() as? MOEffect
-
- //没有礼物类别的情况 - 比如心愿单送礼
- let dict: [String : Any] = ["roomId": roomId,
- "userId": toUid,
- "giftId": giftId,
- "skinCode": skinCode,
- "count": num]
-
- MOHttpManager.shared().toGivingPackGift(withParams: dict) { [weak self] data, error in
- guard let self, self.curRoomId == roomId else { return }
- guard let data = data as? [AnyHashable: Any] else {
- completion?(false)
- return
- }
- if !data.isCodeSuccess {
- if data.code != 20007 {
- data.showNetError()
- }
- completion?(false)
- return
- }
- guard let resData = data.data else {
- completion?(false)
- return
- }
-
- var newItem: MOGiftlist? = nil
- if let bagData = resData["packGiftInfo"] as? [AnyHashable: Any],
- let bag = MOGiftlist.modelObject(with: bagData),
- !bag.giftInfo.id.isEmpty {
- bag.isBag = gift.isBag
- newItem = bag
- }
-
- notifyUserLevelChanged(resData["userLevel"])
-
- notifyGift.isBag = true
- let rebateDiamond = Double(resData.intValue(for: "rebateDiamond"))
- notifyGift.giftInfo.rebateMultiple = Double(resData.intValue(for: "rebateMultiple"))
- notifyGift.giftInfo.rebateDiamond = rebateDiamond
- notifyGift.endGiftNum = num
- notifyGift.giftInfo.selectSkin = skin
- notifyGift.giftInfo.antiDrillCritGift = giftInfo.antiDrillCritGift
- if giftInfo.antiDrillCritGift {
- notifyGift.giftInfo.hitDiamond = Int(rebateDiamond)
- }
- notifySendBagSuccess(category, num, notifyGift, giftInfo, newItem)
- completion?(true)
- }
- }
-
- func sendBag(toUids: [String], category: Int, gift: MOGiftlist, num: Int, completion: ((Bool) -> Void)? = nil) {
- guard !toUids.isEmpty else {
- MBProgressHUD.showTipMessage(inWindow: NSLocalizedString("mimo_2_live_gift_send_0_tip", comment: ""))
- completion?(false)
- return
- }
- guard let roomId = curRoomId,
- !roomId.isEmpty,
- let giftInfo = gift.giftInfo,
- let giftId = giftInfo.id,
- !giftId.isEmpty,
- let notifyGift = gift.copy() as? MOGiftlist
- else {
- completion?(false)
- return
- }
- let skinCode: Double = if let skin = gift.giftInfo.selectSkin {
- skin.code
- } else {
- 0
- }
- let skin = gift.giftInfo.selectSkin?.copy() as? MOEffect
-
- //没有礼物类别的情况 - 比如心愿单送礼
- let dict: [String : Any] = ["roomId": roomId,
- "userIds": toUids,
- "giftId": giftId,
- "skinCode": skinCode,
- "count": num]
-
- MOHttpManager.shared().toSendMoreOneGiftAboutPack(withParams: dict) { [weak self] data, error in
- guard let self, self.curRoomId == roomId else { return }
- guard let data = data as? [AnyHashable: Any] else {
- completion?(false)
- return
- }
- if !data.isCodeSuccess {
- if data.code != 20007 {
- data.showNetError()
- }
- completion?(false)
- return
- }
- guard let resData = data.data,
- let resultData = MOGiftResultData.modelObject(with: resData)
- else {
- completion?(false)
- return
- }
-
- var newItem: MOGiftlist? = nil
- if let bagData = resData["packGiftInfo"] as? [AnyHashable: Any],
- let bag = MOGiftlist.modelObject(with: bagData),
- !bag.giftInfo.id.isEmpty {
- bag.isBag = gift.isBag
- newItem = bag
- }
-
- notifyUserLevelChanged(resData["userLevel"])
-
- var rebateDiamond: Double = 0
- var rebateMultiple: Double = 0
- for item in resultData.giftRebates {
- if let rebate = item as? MOGiftRebates {
- rebateMultiple += rebate.multiple
- rebateDiamond += rebate.diamond
- }
- }
-
- notifyGift.giftInfo.rebateMultiple = rebateMultiple
- notifyGift.giftInfo.rebateDiamond = rebateDiamond
- notifyGift.giftInfo.num = Double(num)
- notifyGift.endGiftNum = num
- notifyGift.giftInfo.multipleUserList = toUids
- notifyGift.giftInfo.selectSkin = skin
- notifyGift.giftInfo.antiDrillCritGift = giftInfo.antiDrillCritGift
- if giftInfo.antiDrillCritGift {
- notifyGift.giftInfo.hitDiamond = Int(rebateDiamond)
- }
- notifySendBagSuccess(category, num * toUids.count, notifyGift, giftInfo, newItem)
- completion?(true)
- }
- }
- }
- // MARK: Gift 礼物
- extension MOGiftListViewModel {
- func sendGift(toUid: String, category: Int, gift: MOGiftlist, num: Int, completion: ((Bool) -> Void)? = nil) {
- guard !toUid.isEmpty else {
- MBProgressHUD.showTipMessage(inWindow: NSLocalizedString("mimo_2_live_gift_send_0_tip", comment: ""))
- completion?(false)
- return
- }
- guard let roomId = curRoomId,
- !roomId.isEmpty,
- let giftInfo = gift.giftInfo,
- let giftId = giftInfo.id,
- !giftId.isEmpty,
- let notifyGift = gift.copy() as? MOGiftlist
- else {
- completion?(false)
- return
- }
- let skinCode: Double = if let skin = gift.giftInfo.selectSkin {
- skin.code
- } else {
- 0
- }
- let skin = gift.giftInfo.selectSkin?.copy() as? MOEffect
-
- //没有礼物类别的情况 - 比如心愿单送礼
- let dict: [String : Any] = ["roomId": roomId,
- "userId": toUid,
- "giftId": giftId,
- "skinCode": skinCode,
- "count": num]
-
- MOHttpManager.shared().toGivingGiftAboutLive(withParams: dict) { [weak self] data, error in
- guard let self, self.curRoomId == roomId else { return }
- guard let data = data as? [AnyHashable: Any] else {
- completion?(false)
- return
- }
- if !data.isCodeSuccess {
- if data.code != 20007 {
- data.showNetError()
- }
- completion?(false)
- return
- }
- guard let resData = data.data else {
- completion?(false)
- return
- }
-
- // MOLogV(@"givingGift: %@",[[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:data options:0 error:nil] encoding:NSUTF8StringEncoding]);
-
- let currentDiamond = resData.intValue(for: "currentDiamond")
- notifyUserBalanceChanged(currentDiamond)
- notifyUserLevelChanged(resData["userLevel"])
-
- let rebateDiamond = Double(resData.intValue(for: "rebateDiamond"))
- notifyGift.giftInfo.rebateMultiple = Double(resData.intValue(for: "rebateMultiple"))
- notifyGift.giftInfo.rebateDiamond = rebateDiamond
- notifyGift.giftInfo.num = Double(num)
- notifyGift.endGiftNum = num
- notifyGift.giftInfo.selectSkin = skin
-
- if let blindboxLotteryDict = resData["blindboxLotterys"] {
- notifyGift.giftInfo.blindboxLottery = MOBlindboxLottery.model(withJSON: blindboxLotteryDict)
- } else {
- notifyGift.giftInfo.blindboxLottery = nil
- }
- notifyGift.giftInfo.antiDrillCritGift = giftInfo.antiDrillCritGift
- if giftInfo.antiDrillCritGift {
- notifyGift.giftInfo.hitDiamond = Int(rebateDiamond)
- }
- notifySendGiftSuccess(category, num, notifyGift, giftInfo)
- completion?(true)
- }
- }
-
- func sendGift(toUids: [String], category: Int, gift: MOGiftlist, num: Int, completion: ((Bool) -> Void)? = nil) {
- guard !toUids.isEmpty else {
- MBProgressHUD.showTipMessage(inWindow: NSLocalizedString("mimo_2_live_gift_send_0_tip", comment: ""))
- completion?(false)
- return
- }
- guard let roomId = curRoomId,
- !roomId.isEmpty,
- let giftInfo = gift.giftInfo,
- let giftId = giftInfo.id,
- !giftId.isEmpty,
- let notifyGift = gift.copy() as? MOGiftlist
- else {
- completion?(false)
- return
- }
- let skinCode: Double = if let skin = gift.giftInfo.selectSkin {
- skin.code
- } else {
- 0
- }
- let skin = gift.giftInfo.selectSkin?.copy() as? MOEffect
-
- //没有礼物类别的情况 - 比如心愿单送礼
- let dict: [String : Any] = ["roomId": roomId,
- "userIds": toUids,
- "giftId": giftId,
- "skinCode": skinCode,
- "count": num]
-
- MOHttpManager.shared().toSendMoreOneGift(withParams: dict) { [weak self] data, error in
- guard let self, self.curRoomId == roomId else { return }
- guard let data = data as? [AnyHashable: Any] else {
- completion?(false)
- return
- }
- if !data.isCodeSuccess {
- if data.code != 20007 {
- data.showNetError()
- }
- completion?(false)
- return
- }
- guard let resData = data.data,
- let resultData = MOGiftResultData.modelObject(with: resData)
- else {
- completion?(false)
- return
- }
-
- notifyUserBalanceChanged(Int(resultData.currentDiamond))
- notifyUserLevelChanged(resData["userLevel"])
-
- var rebateDiamond: Double = 0
- var rebateMultiple: Double = 0
- for item in resultData.giftRebates {
- if let rebate = item as? MOGiftRebates {
- rebateMultiple += rebate.multiple
- rebateDiamond += rebate.diamond
- }
- }
-
- notifyGift.giftInfo.rebateMultiple = rebateMultiple
- notifyGift.giftInfo.rebateDiamond = rebateDiamond
- notifyGift.giftInfo.num = Double(num)
- notifyGift.endGiftNum = num
- notifyGift.giftInfo.multipleUserList = toUids
- notifyGift.giftInfo.selectSkin = skin
-
- if let blindboxLotteryDict = data["blindboxLotterys"] {
- notifyGift.giftInfo.blindboxLottery = MOBlindboxLottery.model(withJSON: blindboxLotteryDict)
- } else {
- notifyGift.giftInfo.blindboxLottery = nil
- }
- notifyGift.giftInfo.antiDrillCritGift = giftInfo.antiDrillCritGift
- if giftInfo.antiDrillCritGift {
- notifyGift.giftInfo.hitDiamond = Int(rebateDiamond)
- }
- notifySendGiftSuccess(category, num, notifyGift, giftInfo)
- completion?(true)
- }
- }
-
- func preloadGiftList() {
- categories.forEach { item in
- loadGiftList(category: Int(item.code), reload: true, completion: nil)
- }
- }
-
- func isGiftListHasNext(_ category: Int) -> Bool {
- guard let tag = giftNextTags[category] else { return true }
- return tag.count > 0
- }
-
- func giftListFor(_ category: Int) -> [MOGiftlist] {
- giftCache[category] ?? []
- }
-
- func loadGiftList(category: Int, reload: Bool = false, completion:((Bool) -> Void)?) {
- guard let roomId = curRoomId else { return }
- let next = reload ? "" : giftNextTags[category] ?? ""
-
- let page: [String : Any] = ["size": Self.kPageSize, "next": next]
- let dic: [String: Any] = ["category": category, "roomId": roomId, "page": page]
-
- MOHttpManager.shared().toGetLiveGiftList(withParams: dic) { [weak self] data, error in
- guard let self, self.curRoomId == roomId else { return }
- guard let data = data as? [AnyHashable: Any] else {
- completion?(false)
- return
- }
- if !data.isCodeSuccess {
- data.showNetError()
- completion?(false)
- return
- }
- guard let resData = data.data else {
- completion?(false)
- return
- }
- guard let baseData = MOGiftListBaseData.modelObject(with: resData),
- let list = baseData.giftlist as? [MOGiftlist] else {
- completion?(false)
- return
- }
-
- var cache = giftCache[category] ?? []
- var isChanged = false
- if reload {
- // 刷新的时候,判断列表是否变化,减少列表没必要的刷新
- isChanged = cache != list
- if isChanged {
- cache.removeAll()
- cache.append(contentsOf: list)
- }
- } else {
- isChanged = true
- cache.append(contentsOf: list)
- }
- if isChanged {
- giftCache[category] = cache
- }
-
- giftNextTags[category] = list.count < Self.kPageSize ? "" : baseData.next
- completion?(true)
-
- if isChanged {
- notifyGiftListChanged(category)
- }
- }
- }
- }
- // MARK: Observers 监听
- extension MOGiftListViewModel {
- func addObserver(_ observer: MOGiftListViewModelDelegate) {
- guard !observers.contains(observer) else { return }
-
- observers.add(observer)
- }
-
- private func notifyGiftListChanged(_ category: Int) {
- let list = giftCache[category] ?? []
- observers.allObjects.forEach { $0.onGiftListChanged?(category: category, list: list) }
- }
-
- private func notifyUserBalanceChanged(_ cur: Int) {
- guard cur != -1 else { return }
- // 更新用户余额
- let userInfo = MODataCache.sharedYYCache().object(forKey: kMineUserInfo) as? MOMeDataInfo
- userInfo?.userWallet.diamond = Double(cur)
- MODataCache.sharedYYCache().setObject(userInfo, forKey: kMineUserInfo)
-
- observers.allObjects.forEach { $0.onUserBalanceChangedBySendGift?(current: cur) }
- }
-
- private func notifyUserLevelChanged(_ data: Any?) {
- guard let levelDic = data as? [AnyHashable: Any] else { return }
- //等级 - 经验
- let level = levelDic.intValue(for: "leel")
- let curExp = levelDic.intValue(for: "currExp")
- let nextExp = levelDic.intValue(for: "nextExp")
- observers.allObjects.forEach { $0.onUserLevelChangedBySendGift?(level: level, curExp: curExp, nextExp: nextExp) }
- }
-
- private func notifySendGiftSuccess(_ category: Int, _ num: Int, _ gift: MOGiftlist, _ info: MOGiftInfo) {
- observers.allObjects.forEach { $0.onSendGiftSuccess?(category: category, num: num, gift: gift, info: info) }
- }
-
- private func notifySendBagSuccess(_ category: Int, _ num: Int, _ gift: MOGiftlist, _ info: MOGiftInfo, _ newItem: MOGiftlist?) {
- observers.allObjects.forEach { $0.onSendBagSuccess?(category: category, num: num, gift: gift, info: info, newItem: newItem) }
- }
- }
- extension MOGiftListViewModel/*: RoomMainEvent*/ {
- func onJoinedRoom(room: MOLiveDetail) {
- guard room.currentRoom.id != curRoomId else { return }
- curRoom = room
- giftCache.removeAll()
- giftNextTags.removeAll()
- checkGiftCategory()
- }
- }
|