| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- //
- // LNRoomGiftHeaderView.swift
- // Gami
- //
- // Created by OneeChan on 2026/3/23.
- //
- import Foundation
- import UIKit
- import SnapKit
- class LNRoomGiftHeaderView: UIView {
- private let roomSeatsView = UIView()
- private let stackView = UIStackView()
-
- private let specifiedUserView = LNRoomGiftSpecifiedUserView()
-
- private weak var roomSession: LNRoomViewModel?
- private var headers: [LNRoomSeatNum: LNRoomGiftAvatarView] = [:]
- var selection: [String] {
- if !roomSeatsView.isHidden {
- headers.map { $1 }.filter { !$0.isHidden && $0.isSelected }.compactMap { $0.curSeatItem?.uid }
- } else if let uid = specifiedUserView.curUid {
- [uid]
- } else {
- []
- }
- }
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- setupViews()
- LNEventDeliver.addObserver(self)
- }
-
- func update(_ room: LNRoomViewModel?, selectedUid: String?) {
- roomSession = room
- if selectedUid == nil
- || room?.seatsInfo.contains(where: { $0.uid == selectedUid }) == true {
- onRoomSeatsChanged()
-
- roomSeatsView.isHidden = false
- specifiedUserView.isHidden = true
- } else {
- roomSeatsView.isHidden = true
- specifiedUserView.isHidden = false
- }
- if let selectedUid {
- headers.first { $1.curSeatItem?.uid == selectedUid }?.value.isSelected = true
- specifiedUserView.update(selectedUid)
- }
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension LNRoomGiftHeaderView: LNRoomViewModelNotify {
- func onRoomSeatsChanged() {
- guard let seats = roomSession?.seatsInfo.sorted(by: { $0.index.rawValue < $1.index.rawValue }) else { return }
- if headers.count != seats.count {
- stackView.arrangedSubviews.forEach {
- stackView.removeArrangedSubview($0)
- $0.removeFromSuperview()
- }
-
- for seat in seats {
- let avatar = LNRoomGiftAvatarView()
- avatar.isSelected = false
- avatar.onTap { [weak avatar] in
- guard let avatar else { return }
- avatar.isSelected.toggle()
- }
- avatar.update(seat)
- stackView.addArrangedSubview(avatar)
- headers[seat.index] = avatar
- }
- } else {
- for seat in seats {
- headers[seat.index]?.update(seat)
- }
- }
- }
- }
- private extension LNRoomGiftHeaderView {
- func setupViews() {
- let titleLabel = UILabel()
- titleLabel.font = .body_l
- titleLabel.textColor = .text_2
- titleLabel.text = .init(key: "B00129")
- addSubview(titleLabel)
- titleLabel.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(10)
- make.centerY.equalToSuperview()
- }
-
- let roomSeatsView = buildRoomSeatsView()
- addSubview(roomSeatsView)
- roomSeatsView.snp.makeConstraints { make in
- make.leading.equalTo(titleLabel.snp.trailing).offset(6)
- make.trailing.equalToSuperview().offset(-10)
- make.verticalEdges.equalToSuperview()
- make.height.equalTo(40)
- }
-
- let userView = buildSpecifiedUserView()
- addSubview(userView)
- userView.snp.makeConstraints { make in
- make.leading.equalTo(titleLabel.snp.trailing).offset(6)
- make.trailing.equalToSuperview().offset(-10)
- make.centerY.equalToSuperview()
- }
- }
-
- private func buildRoomSeatsView() -> UIView {
- let scrollView = UIScrollView()
- scrollView.showsHorizontalScrollIndicator = false
- scrollView.contentInset = .init(top: 0, left: 0, bottom: 0, right: 32)
- roomSeatsView.addSubview(scrollView)
- scrollView.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- }
-
- stackView.spacing = 6
- stackView.axis = .horizontal
- scrollView.addSubview(stackView)
- stackView.snp.makeConstraints { make in
- make.edges.equalToSuperview()
- make.height.equalToSuperview()
- }
-
- let gradientView = UIView.gradientView([
- .fill_7.withAlphaComponent(0), .fill_7
- ], .horizontalLTR)
- roomSeatsView.addSubview(gradientView)
- gradientView.snp.makeConstraints { make in
- make.verticalEdges.equalToSuperview()
- make.trailing.equalToSuperview()
- make.width.equalTo(32)
- }
-
- return roomSeatsView
- }
-
- private func buildSpecifiedUserView() -> UIView {
-
- return specifiedUserView
- }
- }
- private class LNRoomGiftAvatarView: UIView {
- private let avatarBg = UIView()
- private let avatarView = UIImageView()
- private let badgeBg = UIView()
- private let badge = UILabel()
- private(set) var curSeatItem: LNRoomSeatItem?
-
- var isSelected: Bool = false {
- didSet {
- if isSelected {
- avatarBg.layer.borderColor = UIColor.text_6.cgColor
- badge.textColor = .text_1
- badgeBg.backgroundColor = .text_6
- } else {
- avatarBg.layer.borderColor = UIColor.clear.cgColor
- badge.textColor = .text_4
- badgeBg.backgroundColor = .text_1
- }
- }
- }
-
- func update(_ seat: LNRoomSeatItem) {
- isHidden = seat.uid.isEmpty || seat.uid.isMyUid
- avatarView.sd_setImage(with: URL(string: seat.avatar))
- badge.text = seat.index.giftHeaderTitle
-
- curSeatItem = seat
- }
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- snp.makeConstraints { make in
- make.width.height.equalTo(40)
- }
-
- avatarBg.backgroundColor = .clear
- avatarBg.layer.cornerRadius = 17
- avatarBg.layer.borderWidth = 1
- avatarBg.layer.borderColor = UIColor.primary_4.cgColor
- addSubview(avatarBg)
- avatarBg.snp.makeConstraints { make in
- make.width.height.equalTo(34)
- make.centerX.equalToSuperview()
- make.top.equalToSuperview().offset(1)
- make.bottom.equalToSuperview().offset(-5)
- }
-
- avatarView.layer.cornerRadius = 15
- avatarView.clipsToBounds = true
- avatarView.contentMode = .scaleAspectFill
- avatarBg.addSubview(avatarView)
- avatarView.snp.makeConstraints { make in
- make.center.equalToSuperview()
- make.width.height.equalTo(30)
- }
-
- badgeBg.backgroundColor = .fill
- badgeBg.layer.cornerRadius = 6
- addSubview(badgeBg)
- badgeBg.snp.makeConstraints { make in
- make.centerX.equalToSuperview()
- make.bottom.equalToSuperview().offset(-2)
- make.height.equalTo(12)
- make.leading.greaterThanOrEqualToSuperview()
- make.width.greaterThanOrEqualTo(26)
- }
-
- badge.font = .systemFont(ofSize: 10)
- badge.textColor = .text_4
- badge.textAlignment = .center
- badgeBg.addSubview(badge)
- badge.snp.makeConstraints { make in
- make.center.equalToSuperview()
- make.horizontalEdges.equalToSuperview().inset(4)
- }
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- private class LNRoomGiftSpecifiedUserView: UIView {
- private let nameLabel = UILabel()
- private let avatar = UIImageView()
- private(set) var curUid: String?
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- let avatarBg = UIView()
- avatarBg.backgroundColor = .clear
- avatarBg.layer.cornerRadius = 17
- avatarBg.layer.borderWidth = 1
- avatarBg.layer.borderColor = UIColor.primary_4.cgColor
- addSubview(avatarBg)
- avatarBg.snp.makeConstraints { make in
- make.width.height.equalTo(34)
- make.leading.equalToSuperview()
- make.verticalEdges.equalToSuperview()
- }
-
- avatar.layer.cornerRadius = 15
- avatar.clipsToBounds = true
- avatar.contentMode = .scaleAspectFill
- avatarBg.addSubview(avatar)
- avatar.snp.makeConstraints { make in
- make.center.equalToSuperview()
- make.width.height.equalTo(30)
- }
-
- nameLabel.font = .body_s
- nameLabel.textColor = .text_1
- addSubview(nameLabel)
- nameLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalTo(avatarBg.snp.trailing).offset(5)
- make.trailing.equalToSuperview()
- }
- }
-
- func update(_ uid: String?) {
- curUid = uid
- guard let uid, !uid.isEmpty else {
- isHidden = true
- return
- }
-
- LNProfileManager.shared.getCachedProfileUserInfo(uid: uid, fetchIfNeeded: true)
- { [weak self] info in
- guard let self else { return }
- guard let info, info.uid == curUid else { return }
- nameLabel.text = info.name
- avatar.sd_setImage(with: URL(string: info.avatar))
- }
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
|