// // LNRelationManager.swift // Lanu // // Created by OneeChan on 2025/12/12. // import Foundation protocol LNRelationManagerNotify { func onUserRelationChanged(uid: String, relation: LNUserRelationShip) func onMyRelationInfoChanged() func onUserBlackListChanged() } extension LNRelationManagerNotify { func onUserRelationChanged(uid: String, relation: LNUserRelationShip) {} func onMyRelationInfoChanged() {} func onUserBlackListChanged() {} } var myRelationInfo: LNUserRelationStatVO { LNRelationManager.shared.myRelationInfo } extension String { var isInMyBlackList: Bool { LNRelationManager.shared.myBlackList.contains(self) } } struct LNUserRelationShip: OptionSet, Decodable { let rawValue: UInt8 static let followed = LNUserRelationShip(rawValue: 1<<0) static let fans = LNUserRelationShip(rawValue: 1<<1) } class LNRelationManager { static var shared = LNRelationManager() private(set) var myRelationInfo: LNUserRelationStatVO = LNUserRelationStatVO() private var relationIsChanged = false fileprivate var myBlackList = Set() private init() { LNEventDeliver.addObserver(self) } func updateMyRelationInfo(_ info: LNUserRelationStatVO) { myRelationInfo = info notifyUserRelationInfoChanged() } func reloadRelationInfoIfNeed() { guard relationIsChanged else { return } LNProfileManager.shared.reloadMyProfileDetail() relationIsChanged = false } func operateFollow(uid: String, follow: Bool, queue: DispatchQueue = .main, handler: ((Bool) -> Void)?) { LNHttpManager.shared.operateFollow(uid: uid, follow: follow) { [weak self] err in guard let self else { return } if err == nil { getRelationWithUser(uid: uid, handler: nil) if follow { showToast(.init(key: "A00030")) } } queue.asyncIfNotGlobal { handler?(err == nil) } relationIsChanged = true } } func getUserFollowList(next: String, queue: DispatchQueue = .main, handler: @escaping ([LNRelationUserVO]?, String?, Int?) -> Void) { LNHttpManager.shared.getUserFollowList(size: 30, next: next) { res, err in queue.asyncIfNotGlobal { handler(res?.list, res?.next, res?.total) } } } func getUserFansList(next: String, queue: DispatchQueue = .main, handler: @escaping ([LNRelationUserVO]?, String?, Int?) -> Void) { LNHttpManager.shared.getUserFansList(size: 30, next: next) { res, err in queue.asyncIfNotGlobal { handler(res?.list, res?.next, res?.total) } } } func getRelationWithUser(uid: String, queue: DispatchQueue = .main, handler: ((LNUserRelationShip?) -> Void)?) { LNHttpManager.shared.getRelationWithUser(uid: uid) { [weak self] res, err in guard let self else { return } queue.asyncIfNotGlobal { [weak self] in guard let self else { return } handler?(res?.list.first?.relateion) if let relation = res?.list.first?.relateion { notifyRelationChanged(uid: uid, relation: relation) } } } } } extension LNRelationManager { func blackListUser(uid: String, black: Bool, queue: DispatchQueue = .main, handler: ((Bool) -> Void)?) { LNHttpManager.shared.blackListUser(uid: uid, black: black) { [weak self] err in guard let self else { return } queue.asyncIfNotGlobal { handler?(err == nil) } if black { myBlackList.insert(uid) } else { myBlackList.remove(uid) } notifyUserBlackListChanged() } } private func reloadMyBlackList() { var next = "" var list: [LNUserBlackVO] = [] func _loadList() { LNHttpManager.shared.getBlackList(size: 30, next: next) { [weak self] res, err in guard let self else { return } guard let res, err == nil else { return } list.append(contentsOf: res.list) next = res.next if next.isEmpty { myBlackList.formUnion(list.map({ $0.userNo })) notifyUserBlackListChanged() } else { _loadList() } } } _loadList() } } extension LNRelationManager: LNAccountManagerNotify { func onUserLogin() { myRelationInfo = LNUserRelationStatVO() myBlackList.removeAll() reloadMyBlackList() } } extension LNRelationManager { private func notifyRelationChanged(uid: String, relation: LNUserRelationShip) { LNEventDeliver.notifyEvent { ($0 as? LNRelationManagerNotify)?.onUserRelationChanged(uid: uid, relation: relation) } } private func notifyUserRelationInfoChanged() { LNEventDeliver.notifyEvent { ($0 as? LNRelationManagerNotify)?.onMyRelationInfoChanged() } } private func notifyUserBlackListChanged() { LNEventDeliver.notifyEvent { ($0 as? LNRelationManagerNotify)?.onUserBlackListChanged() } } }