| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- //
- // LNOrderRoomUserSeatView.swift
- // Gami
- //
- // Created by OneeChan on 2026/3/23.
- //
- import Foundation
- import UIKit
- import SnapKit
- class LNOrderRoomUserSeatView: UIView {
- private let seatNum: LNOrderRoomSeatNum
- private let nameLabel = UILabel()
- private let emptyIc = UIImageView()
- private var emptyIcon: UIImage {
- switch seatNum {
- case .host: .icSeatNormal
- case .guest: .icSeatGuest
- default: .icSeatNormal
- }
- }
-
- private let userView = UIView()
- private let userAvatar = UIImageView()
- private let muteIc = UIImageView()
- private let speakingView = LNRoomSeatSpeakingView()
-
- private weak var roomSession: LNOrderRoomViewModel?
- private var curSeat: LNRoomSeatItem? {
- roomSession?.seatsInfo.first { $0.index == seatNum.rawValue }
- }
- private var isSpeaking: Bool {
- roomSession?.speakingUser.contains(curSeat?.uid ?? "") == true
- }
-
- init(seatNum: LNOrderRoomSeatNum) {
- self.seatNum = seatNum
- super.init(frame: .zero)
-
- setupViews()
- LNEventDeliver.addObserver(self)
- }
-
- func update(_ room: LNOrderRoomViewModel?) {
- roomSession = room
- if let room {
- onRoomSeatsChanged(session: room, changed: room.seatsInfo)
- speakingView.update(seatNum.rawValue, room: room)
- }
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension LNOrderRoomUserSeatView {
- private func handlerClick() {
- guard let room = roomSession, let seat = curSeat else { return }
- guard let orderSeatNum = LNOrderRoomSeatNum(rawValue: seat.index) else { return }
- let mySeatNum = LNOrderRoomSeatNum(rawValue: room.mySeatInfo?.index ?? -1) ?? .none
-
- let sheet = LNRoomSheetMenu()
-
- let invite = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00341"), handler: { [weak sheet, weak self] in
- guard let self, let sheet else { return }
- sheet.dismiss()
-
- let panel = LNOrderRoomInviteSeatPanel()
- panel.update(seat, room: room)
- panel.popup(self)
- })
-
- let closeMic = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00342"), handler: { [weak sheet] in
- guard let sheet else { return }
- room.lockSeat(num: seat.index) { [weak sheet] success in
- guard let sheet else { return }
- guard success else { return }
- sheet.dismiss()
- }
- })
-
- let openMic = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00348"), handler: { [weak sheet] in
- guard let sheet else { return }
- room.unlockSeat(num: seat.index) { [weak sheet] success in
- guard let sheet else { return }
- guard success else { return }
- sheet.dismiss()
- }
- })
-
- let muteMic = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00343"), handler: { [weak sheet] in
- guard let sheet else { return }
- sheet.dismiss()
-
- room.muteSeat(uid: seat.uid) { _ in }
- })
-
- let unmuteMic = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00349"), handler: { [weak sheet] in
- guard let sheet else { return }
- sheet.dismiss()
-
- room.unmuteSeat(uid: seat.uid) { _ in }
- })
-
- let profile = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00344"), handler: { [weak sheet] in
- guard let sheet else { return }
- sheet.dismiss()
-
- let panel = LNRoomProfileCardPanel()
- panel.load(seat.uid)
- panel.popup(self)
- })
-
- let kickOffMic = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00345"), handler: { [weak sheet] in
- guard let sheet else { return }
- room.kickUserOffSeat(uid: seat.uid) { [weak sheet] success in
- guard let sheet else { return }
- guard success else { return }
- sheet.dismiss()
- }
- })
-
- let offMic = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00346"), handler: { [weak sheet] in
- guard let sheet else { return }
- room.leaveSeat { [weak sheet] success in
- guard let sheet else { return }
- guard success else { return }
- sheet.dismiss()
- }
- })
-
- let toBePlaymate = LNRoomSheetMenu.buildMenuItem(title: .init(key: "A00347"), handler: { [weak sheet] in
- guard let sheet else { return }
- showLoading()
- LNGameMateManager.shared.getJoinGameMateInfo { [weak sheet] res in
- dismissLoading()
- guard let sheet else { return }
- guard let res else { return }
- sheet.dismiss()
-
- if res.step3Complete || res.underReview {
- sheet.pushToJoinUsReview(true)
- return
- }
- let config = LNJumpWebViewConfig(url: .joinUsUrl)
- sheet.pushToWebView(config)
- }
- })
-
- if seat.uid.isMyUid { // 自己
- sheet.update(title: nil, views: [
- offMic, profile
- ])
- } else if room.mySeatInfo?.index == LNOrderRoomSeatNum.host.rawValue { // 管理员
- if seat.uid.isEmpty { // 空麦位
- if seat.isLocked {
- sheet.update(title: orderSeatNum.title, views: [
- openMic
- ])
- } else {
- sheet.update(title: orderSeatNum.title, views: [
- invite, closeMic
- ])
- }
- } else { // 有人的麦位
- sheet.update(title: orderSeatNum.title, views: [
- profile, kickOffMic, closeMic, seat.isMute ? unmuteMic : muteMic
- ])
- }
- } else {
- if seat.isLocked { return } // 麦位被锁,仅管理员能操作
-
- if !seat.uid.isEmpty { // 有人的麦位
- let panel = LNRoomProfileCardPanel()
- panel.load(seat.uid)
- panel.popup(self)
- return
- }
-
- if myUserInfo.playmate { // 陪玩师
- if orderSeatNum == .host
- || orderSeatNum == .guest
- || !(.mic1 ... .mic8 ~= mySeatNum) {
- let panel = LNOrderRoomApplySeatPanel()
- panel.update(room, seat: orderSeatNum)
- panel.popup(self)
- return
- }
- return
- } else { // 普通用户
- if orderSeatNum == .host || orderSeatNum == .guest { // 主持人 和 嘉宾位
- let panel = LNOrderRoomApplySeatPanel()
- panel.update(room, seat: orderSeatNum)
- panel.popup(self)
- return
- } else {
- sheet.update(title: nil, views: [
- toBePlaymate
- ])
- }
- }
- }
-
- sheet.popup(self)
- }
- }
- extension LNOrderRoomUserSeatView: LNRoomViewModelNotify {
- func onRoomSeatsChanged(session: LNRoomSession, changed: [LNRoomSeatItem]) {
- guard roomSession == session else { return }
- guard let curSeat else { return }
-
- if curSeat.isLocked {
- userView.isHidden = true
- emptyIc.image = .icSeatLock
-
- nameLabel.text = seatNum.title
- } else if curSeat.uid.isEmpty {
- userView.isHidden = true
- emptyIc.image = emptyIcon
-
- nameLabel.text = seatNum.title
- } else {
- userView.isHidden = false
-
- if !curSeat.nickname.isEmpty {
- userAvatar.sd_setImage(with: URL(string: curSeat.avatar))
- nameLabel.text = curSeat.nickname
- } else {
- LNProfileManager.shared.getCachedProfileUserInfo(uid: curSeat.uid) { [weak self] info in
- guard let self, let info, info.uid == curSeat.uid else { return }
- userAvatar.sd_setImage(with: URL(string: info.avatar))
- nameLabel.text = info.name
- }
- }
- }
-
- muteIc.isHidden = !curSeat.isMute
- }
- }
- extension LNOrderRoomUserSeatView {
- private func setupViews() {
- onTap { [weak self] in
- guard let self else { return }
- handlerClick()
- }
- snp.makeConstraints { make in
- make.width.equalTo(76)
- make.height.equalTo(68)
- }
-
- let empty = buildEmpty()
- addSubview(empty)
- empty.snp.makeConstraints { make in
- make.centerX.equalToSuperview()
- make.top.equalToSuperview()
- }
-
- let userView = buildUserView()
- addSubview(userView)
- userView.snp.makeConstraints { make in
- make.centerX.equalToSuperview()
- make.top.equalToSuperview()
- }
-
- let bottom = buildBottom()
- addSubview(bottom)
- bottom.snp.makeConstraints { make in
- make.centerX.equalToSuperview()
- make.bottom.equalToSuperview()
- make.leading.greaterThanOrEqualToSuperview()
- }
- }
-
- private func buildEmpty() -> UIView {
- emptyIc.image = .icSeatNormal
-
- return emptyIc
- }
-
- private func buildUserView() -> UIView {
- userView.isHidden = true
- userView.snp.makeConstraints { make in
- make.width.height.equalTo(46)
- }
-
- userView.addSubview(speakingView)
- speakingView.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- }
-
- let gradientBg = UIImageView()
- gradientBg.layer.cornerRadius = 23
- gradientBg.image = .primary_7
- gradientBg.clipsToBounds = true
- userView.addSubview(gradientBg)
- gradientBg.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- }
-
- userAvatar.layer.cornerRadius = 22
- userAvatar.clipsToBounds = true
- userView.addSubview(userAvatar)
- userAvatar.snp.makeConstraints { make in
- make.center.equalToSuperview()
- make.width.height.equalTo(44)
- }
-
- muteIc.image = .icMicOffBlack70
- userView.addSubview(muteIc)
- muteIc.snp.makeConstraints { make in
- make.trailing.equalToSuperview()
- make.bottom.equalToSuperview()
- }
-
- return userView
- }
-
- private func buildBottom() -> UIView {
- let stackView = UIStackView()
- stackView.spacing = 2
- stackView.alignment = .center
-
- let hostIc = UIImageView(image: .icMicRoomHost)
- hostIc.isHidden = seatNum != .host
- stackView.addArrangedSubview(hostIc)
-
- nameLabel.font = .body_xs
- nameLabel.textColor = .text_1
- nameLabel.textAlignment = .center
- stackView.addArrangedSubview(nameLabel)
-
- return stackView
- }
- }
|