LNRoomManager.swift 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. //
  2. // LNRoomManager.swift
  3. // Gami
  4. //
  5. // Created by OneeChan on 2026/3/9.
  6. //
  7. import Foundation
  8. import AtomicXCore
  9. import RTCRoomEngine
  10. protocol LNRoomManagerNotify {
  11. func onUserRoomAbilityChanged()
  12. func onHallEntranceChanged()
  13. }
  14. extension LNRoomManagerNotify {
  15. func onUserRoomAbilityChanged() { }
  16. func onHallEntranceChanged() { }
  17. }
  18. func showTencentError(_ error: ErrorInfo) {
  19. let items = error.message.components(separatedBy: ",")
  20. for item in items {
  21. let parts = item.components(separatedBy: ":")
  22. if parts.first?.trimmingCharacters(in: .whitespaces) == "error_message" {
  23. showToast(parts.dropFirst().joined(separator: ":").trimmingCharacters(in: .whitespaces))
  24. return
  25. }
  26. }
  27. showToast(error.message)
  28. }
  29. class LNRoomManager {
  30. static let shared = LNRoomManager()
  31. static let RoomNameMinInput = 2
  32. static let RoomNameMaxInput = 20
  33. static let MicNum = 10
  34. static private(set) var hallEntrance = false {
  35. didSet {
  36. if oldValue != hallEntrance {
  37. LNEventDeliver.notifyEvent { ($0 as? LNRoomManagerNotify)?.onHallEntranceChanged() }
  38. }
  39. }
  40. }
  41. private(set) var roomAbility: LNRoomAbilityVO?
  42. private(set) weak var curRoom: LNRoomViewModel?
  43. let liveListStore = LiveListStore.shared
  44. init () {
  45. LNEventDeliver.addObserver(self)
  46. }
  47. }
  48. // MARK: 直播间管理
  49. extension LNRoomManager {
  50. func getCreateRoomAbility(queue: DispatchQueue = .main,
  51. handler: ((LNRoomAbilityVO?) -> Void)?)
  52. {
  53. LNHttpManager.shared.getCreateRoomAbility { info, err in
  54. queue.asyncIfNotGlobal {
  55. if let err {
  56. showToast(err.errorDesc)
  57. handler?(nil)
  58. } else {
  59. self.roomAbility = info
  60. handler?(info)
  61. LNEventDeliver.notifyEvent { ($0 as? LNRoomManagerNotify)?.onUserRoomAbilityChanged() }
  62. }
  63. }
  64. }
  65. }
  66. func createRoom(roomName: String, cover: String, queue: DispatchQueue = .main,
  67. forbidAudio: Bool, handler: @escaping (String?) -> Void)
  68. {
  69. leaveRoom { _ in
  70. LNHttpManager.shared.createRoom(roomTitle: roomName, roomCover: cover, forbidAudio: forbidAudio) { room, err in
  71. queue.asyncIfNotGlobal {
  72. handler(room?.roomId)
  73. LNUserDefaults[.joinedRoomId] = room?.roomId
  74. }
  75. if let err {
  76. showToast(err.errorDesc)
  77. }
  78. }
  79. }
  80. }
  81. func joinRoom(roomId: String, queue: DispatchQueue = .main, handler: @escaping (String?) -> Void) {
  82. liveListStore.joinLive(liveID: roomId) { result in
  83. queue.asyncIfNotGlobal {
  84. switch result {
  85. case .success(let info):
  86. handler(info.liveID)
  87. LNUserDefaults[.joinedRoomId] = roomId
  88. case .failure(let errorInfo):
  89. handler(nil)
  90. showTencentError(errorInfo)
  91. self.reportRoomUnavailable(id: roomId, code: errorInfo.code, reason: errorInfo.message)
  92. }
  93. }
  94. }
  95. }
  96. func closeRoom(queue: DispatchQueue = .main, handler: @escaping (Bool) -> Void) {
  97. liveListStore.endLive { result in
  98. queue.asyncIfNotGlobal {
  99. switch result {
  100. case .success:
  101. handler(true)
  102. case .failure(let errorInfo):
  103. handler(false)
  104. showTencentError(errorInfo)
  105. }
  106. }
  107. }
  108. }
  109. func leaveRoom(queue: DispatchQueue = .main, handler: @escaping (Bool) -> Void) {
  110. let curLive: String = curRoom?.roomId ?? LNUserDefaults[.joinedRoomId, ""]
  111. if curLive.isEmpty {
  112. handler(true)
  113. } else {
  114. let json = "{\"api\":\"exitRoom\",\"params\":{\"roomId\":\"\(curLive)\",\"syncWaiting\":true,\"roomType\":2}}"
  115. TUIRoomEngine.sharedInstance().callExperimentalAPI(jsonStr: json) { error in
  116. handler(true)
  117. LNUserDefaults[.joinedRoomId] = ""
  118. }
  119. }
  120. }
  121. func updateCurRoom(_ room: LNRoomViewModel) {
  122. curRoom = room
  123. }
  124. }
  125. // MARK: 入口管理
  126. extension LNRoomManager {
  127. func reloadHallEntrance() {
  128. LNHttpManager.shared.getHallEntrance { res, err in
  129. guard let res else { return }
  130. Self.hallEntrance = res.result
  131. }
  132. }
  133. func getRandomRoom(queue: DispatchQueue = .main, handler: @escaping (LNRoomItemVO?) -> Void) {
  134. LNHttpManager.shared.getRandomRoom { res, err in
  135. queue.asyncIfNotGlobal {
  136. handler(res?.room)
  137. }
  138. if let res, res.room?.roomId.isEmpty != false {
  139. Self.hallEntrance = false
  140. }
  141. if let err {
  142. showToast(err.errorDesc)
  143. }
  144. }
  145. }
  146. func searchRoom(keyword: String, next: String?, queue: DispatchQueue = .main,
  147. handler: @escaping (LNSearchRoomResponse?) -> Void) {
  148. LNHttpManager.shared.searchRoom(keyword: keyword, size: 30, next: next ?? "") { res, err in
  149. queue.asyncIfNotGlobal {
  150. handler(res)
  151. }
  152. if let err {
  153. showToast(err.errorDesc)
  154. }
  155. }
  156. }
  157. func getRoomList(next: String?, queue: DispatchQueue = .main, handler: @escaping (LNSearchRoomResponse?) -> Void) {
  158. LNHttpManager.shared.getRoomList(size: 30, next: next ?? "") { res, err in
  159. queue.asyncIfNotGlobal {
  160. handler(res)
  161. }
  162. if let err {
  163. showToast(err.errorDesc)
  164. }
  165. }
  166. }
  167. func reportRoomUnavailable(id: String, code: Int, reason: String) {
  168. LNHttpManager.shared.reportRoomUnavailable(id: id, code: "\(code)", reason: reason) { _ in }
  169. }
  170. }
  171. // MARK: 用户
  172. extension LNRoomManager {
  173. func getUserCurRoom(uid: String, queue: DispatchQueue = .main,
  174. handler: @escaping (LNUserCurRoomResponse?) -> Void) {
  175. LNHttpManager.shared.getUserCurRoom(uid: uid) { res, err in
  176. queue.asyncIfNotGlobal {
  177. handler(res)
  178. }
  179. if let err {
  180. showToast(err.errorDesc)
  181. }
  182. }
  183. }
  184. }
  185. extension LNRoomManager: LNAccountManagerNotify, LNProfileManagerNotify {
  186. func onUserLogin() {
  187. getCreateRoomAbility(handler: nil)
  188. }
  189. }