This commit is contained in:
启星
2025-08-08 10:49:36 +08:00
parent 6400cf78bb
commit b5ce3d580a
8780 changed files with 978183 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
//
// ChatExtensionRoomSettingsViewController.swift
// TUIRoomKit
//
// Created by janejntang on 2023/6/26.
//
import Foundation
class ChatExtensionRoomSettingsViewController: UIViewController {
let roomView: ChatExtensionRoomSettingsView
init(isOpenMicrophone: Bool, isOpenCamera: Bool) {
let viewModel = ChatExtensionRoomSettingsViewModel(isOpenMicrophone: isOpenMicrophone, isOpenCamera: isOpenCamera)
roomView = ChatExtensionRoomSettingsView(viewModel: viewModel)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
view = roomView
}
override func viewDidLoad() {
setNavBar()
}
private func setNavBar() {
navigationItem.title = .roomDeviceSetText
}
deinit {
debugPrint("deinit \(self)")
}
}
private extension String {
static var roomDeviceSetText: String {
localized("Meeting Settings")
}
}

View File

@@ -0,0 +1,35 @@
//
// InvitedToJoinRoomViewController.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/25.
// Copyright © 2023 Tencent. All rights reserved.
//
import Foundation
class InvitedToJoinRoomViewController: UIViewController {
let roomView: InvitedToJoinRoomView
let viewModel: InvitedToJoinRoomViewModel
init(inviteUserName: String,inviteUserAvatarUrl: String, roomId: String) {
viewModel = InvitedToJoinRoomViewModel(inviteUserName: inviteUserName, inviteUserAvatarUrl:inviteUserAvatarUrl, roomId: roomId)
roomView = InvitedToJoinRoomView(viewModel: viewModel)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
view = roomView
}
override func viewDidDisappear(_ animated: Bool) {
viewModel.stopPlay()
}
deinit {
debugPrint("deinit \(self)")
}
}

View File

@@ -0,0 +1,86 @@
//
// ChatExtensionRoomSettingsItemView.swift
// TUIRoomKit
//
// Created by janejntang on 2023/6/27.
//
import Foundation
class ChatExtensionRoomSettingsItemView: UIView {
let itemData: RoomSetListItemData
let titleLabel: UILabel = {
let view = UILabel()
view.backgroundColor = .clear
view.textColor = .black
view.font = UIFont(name: "PingFangSC-Medium", size: 14)
view.minimumScaleFactor = 0.5
return view
}()
let rightSwitch: UISwitch = {
let view = UISwitch()
view.isOn = true
view.onTintColor = UIColor(0x0062E3)
return view
}()
let line: UIView = {
let view = UIView()
view.backgroundColor = .gray
view.alpha = 0.3
return view
}()
init(itemData: RoomSetListItemData) {
self.itemData = itemData
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private var isViewReady: Bool = false
override func didMoveToWindow() {
super.didMoveToWindow()
guard !isViewReady else { return }
constructViewHierarchy()
activateConstraints()
bindInteraction()
isViewReady = true
}
private func constructViewHierarchy() {
addSubview(titleLabel)
addSubview(rightSwitch)
addSubview(line)
}
private func activateConstraints() {
titleLabel.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(10)
make.centerY.equalToSuperview()
make.width.equalTo(100.scale375())
}
rightSwitch.snp.makeConstraints { make in
make.trailing.equalToSuperview().offset(-10)
make.centerY.equalToSuperview()
}
line.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(10)
make.trailing.equalToSuperview().offset(-10)
make.bottom.equalToSuperview().offset(-2)
make.height.equalTo(0.5)
}
}
private func bindInteraction() {
backgroundColor = .white
titleLabel.text = itemData.titleText
rightSwitch.isOn = itemData.isSwitchOn
rightSwitch.addTarget(self, action: #selector(switchAction(sender:)), for: .touchUpInside)
}
@objc func switchAction(sender: UISwitch) {
itemData.action?(sender)
}
}

View File

@@ -0,0 +1,65 @@
//
// ChatExtensionRoomSettingsView.swift
// TUIRoomKit
//
// Created by janejntang on 2023/6/26.
//
import Foundation
class ChatExtensionRoomSettingsView: UIView {
let viewModel : ChatExtensionRoomSettingsViewModel
let stackView: UIStackView = {
let view = UIStackView()
view.axis = .vertical
view.alignment = .center
view.distribution = .equalSpacing
view.spacing = 0
return view
}()
init(viewModel: ChatExtensionRoomSettingsViewModel) {
self.viewModel = viewModel
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - view layout
private var isViewReady: Bool = false
override func didMoveToWindow() {
super.didMoveToWindow()
guard !isViewReady else { return }
backgroundColor = .white
constructViewHierarchy()
activateConstraints()
isViewReady = true
}
private func constructViewHierarchy() {
addSubview(stackView)
for item in viewModel.roomSettingsViewItems {
let view = ChatExtensionRoomSettingsItemView(itemData: item)
stackView.addArrangedSubview(view)
view.snp.makeConstraints { make in
make.height.equalTo(60.scale375())
make.width.equalToSuperview()
}
}
}
private func activateConstraints() {
stackView.snp.makeConstraints { make in
make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(10)
make.leading.equalToSuperview().offset(10)
make.trailing.equalToSuperview().offset(-10)
}
}
deinit {
debugPrint("deinit \(self)")
}
}

View File

@@ -0,0 +1,178 @@
//
// RoomaInviteView.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/24.
//
import Foundation
class InvitedToJoinRoomView: UIView {
let viewModel : InvitedToJoinRoomViewModel
let userNameLabel: UILabel = {
let label = UILabel()
label.font = UIFont(name: "PingFangSC-Regular", size: 30)
label.textColor = .white
return label
}()
let inviteLabel: UILabel = {
let label = UILabel()
label.font = UIFont(name: "PingFangSC-Regular", size: 15)
label.text = .inviteMeetingText
label.textColor = .white
return label
}()
let userImageView: UIImageView = {
let image = UIImageView()
return image
}()
let disagreeButton: UIButton = {
let button = UIButton(type: .custom)
return button
}()
let disagreeImageView: UIImageView = {
let image = UIImage(named: "room_hangup", in: tuiRoomKitBundle(), compatibleWith: nil)
let imageView = UIImageView(image: image)
return imageView
}()
let disagreeLabel: UILabel = {
let label = UILabel()
label.text = .declineText
label.textColor = .red
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 20.0)
return label
}()
let agreeButton: UIButton = {
let button = UIButton(type: .custom)
return button
}()
let agreeImageView: UIImageView = {
let image = UIImage(named: "room_handsfree_on", in: tuiRoomKitBundle(), compatibleWith: nil)
let imageView = UIImageView(image: image)
return imageView
}()
let agreeLabel: UILabel = {
let label = UILabel()
label.text = .agreeText
label.textColor = .white
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 20.0)
return label
}()
init(viewModel: InvitedToJoinRoomViewModel) {
self.viewModel = viewModel
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - view layout
private var isViewReady: Bool = false
override func didMoveToWindow() {
super.didMoveToWindow()
guard !isViewReady else { return }
backgroundColor = UIColor(0x242424)
constructViewHierarchy()
activateConstraints()
bindInteraction()
isViewReady = true
}
private func constructViewHierarchy() {
addSubview(userNameLabel)
addSubview(inviteLabel)
addSubview(userImageView)
addSubview(disagreeButton)
disagreeButton.addSubview(disagreeImageView)
disagreeButton.addSubview(disagreeLabel)
addSubview(agreeButton)
agreeButton.addSubview(agreeImageView)
agreeButton.addSubview(agreeLabel)
}
private func activateConstraints() {
userNameLabel.snp.makeConstraints { make in
make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(30)
make.trailing.equalToSuperview().offset(-130)
}
inviteLabel.snp.makeConstraints { make in
make.trailing.equalTo(userNameLabel)
make.top.equalTo(userNameLabel.snp.bottom).offset(15)
}
userImageView.snp.makeConstraints { make in
make.top.equalTo(userNameLabel)
make.trailing.equalToSuperview().offset(-20)
make.width.height.equalTo(80)
}
disagreeButton.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-100)
make.width.equalTo(80)
make.height.equalTo(120)
make.leading.equalToSuperview().offset(50)
}
disagreeImageView.snp.makeConstraints { make in
make.top.equalToSuperview()
make.centerX.equalToSuperview()
make.width.height.equalTo(80)
}
disagreeLabel.snp.makeConstraints { make in
make.top.equalTo(disagreeImageView.snp.bottom).offset(5)
make.centerX.equalToSuperview()
make.width.equalTo(80)
make.bottom.equalToSuperview()
}
agreeButton.snp.makeConstraints { make in
make.bottom.equalTo(disagreeButton)
make.width.equalTo(80)
make.height.equalTo(120)
make.trailing.equalToSuperview().offset(-50)
}
agreeImageView.snp.makeConstraints { make in
make.top.equalToSuperview()
make.centerX.equalToSuperview()
make.width.height.equalTo(80)
}
agreeLabel.snp.makeConstraints { make in
make.top.equalTo(agreeImageView.snp.bottom).offset(5)
make.centerX.equalToSuperview()
make.width.equalTo(80)
make.bottom.equalToSuperview()
}
}
private func bindInteraction() {
disagreeButton.addTarget(self, action: #selector(disagreeAction(sender:)), for: .touchUpInside)
agreeButton.addTarget(self, action: #selector(agreeAction(sender:)), for: .touchUpInside)
viewModel.startPlay()
setupViewState()
}
func setupViewState() {
userNameLabel.text = viewModel.inviteUserName
let placeholderImage = UIImage(named: "room_default_avatar", in: tuiRoomKitBundle(), compatibleWith: nil)
userImageView.sd_setImage(with: URL(string: viewModel.avatarUrl), placeholderImage: placeholderImage)
}
@objc private func disagreeAction(sender: UIButton) {
viewModel.disagreeAction()
}
@objc private func agreeAction(sender: UIButton) {
viewModel.agreeAction()
}
deinit {
debugPrint("deinit \(self)")
}
}
private extension String {
static var inviteMeetingText: String {
localized("Invite you to a meeting")
}
static var declineText: String {
localized("Decline")
}
static var agreeText: String {
localized("Agree")
}
}

View File

@@ -0,0 +1,49 @@
//
// RoomMsgCell.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/8.
// Copyright © 2023 Tencent. All rights reserved.
//
import Foundation
import TIMCommon
@objc(RoomMessageBubbleCell)
class RoomMessageBubbleCell: TUIBubbleMessageCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
guard self.container != nil else { return }
let message = RoomMessageModel()
let view = RoomMessageView(viewModel: RoomMessageViewModel(message: message))
self.container.addSubview(view)
view.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func fill(with data: TUIBubbleMessageCellData) {
super.fill(with: data)
let customData = data as? RoomMessageBubbleCellData
guard let messageModel = customData?.messageModel as? RoomMessageModel else { return }
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
let subviewArray = self.container.subviews
for view in subviewArray where view is RoomMessageView {
guard let messageView = view as? RoomMessageView else { continue }
messageView.viewModel.changeMessage(message: messageModel)
}
}
}
override class func getContentSize(_ data: TUIMessageCellData?) -> CGSize {
return CGSize(width: 238, height: 157)
}
deinit {
debugPrint("deinit \(self)")
}
}

View File

@@ -0,0 +1,328 @@
//
// RoomMessageView.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/9.
// Copyright © 2023 Tencent. All rights reserved.
//
class RoomMessageView: UIView {
let viewModel: RoomMessageViewModel
private var viewArray: [UIView] = []
let roomStatusView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(0xD1E4FD)
return view
}()
let roomStatusImageView: UIImageView = {
let image = UIImageView()
return image
}()
let roomStatusLabel: UILabel = {
let label = UILabel()
label.font = UIFont(name: "PingFangSC-Regular", size: 15)
return label
}()
let roomNameLabel: UILabel = {
let label = UILabel()
label.font = UIFont(name: "PingFangSC-Regular", size: 20)
label.textColor = .black
label.adjustsFontSizeToFitWidth = true
return label
}()
let stackView: UIStackView = {
let view = UIStackView()
view.axis = .horizontal
view.alignment = .leading
view.distribution = .equalSpacing
view.spacing = 2
return view
}()
lazy var inviteUserButton: UIButton = {
let button = UIButton()
button.setImage(UIImage(named: "room_chat_invite", in: tuiRoomKitBundle(), compatibleWith: nil), for: .normal)
return button
}()
let userNumberLabel: UILabel = {
let label = UILabel()
label.font = UIFont(name: "PingFangSC-Regular", size: 15)
label.adjustsFontSizeToFitWidth = true
label.textColor = UIColor(0x888888)
label.textAlignment = isRTL ? .right : .left
return label
}()
let enterRoomButton: UIButton = {
let button = UIButton()
button.setTitle(.enterMeetingText, for: .normal)
button.setTitleColor(.white, for: .normal)
button.setBackgroundImage(UIColor.tui_color(withHex: "147AFF").trans2Image(), for: .normal)
button.setTitle(.alreadyEnteredMeeting, for: .selected)
button.setTitleColor(UIColor(0x999999), for: .selected)
button.setBackgroundImage(UIColor.tui_color(withHex: "F3F4F4").trans2Image(), for: .selected)
button.titleLabel?.font = UIFont(name: "PingFangSC-Regular", size: 15)
return button
}()
let enterRoomStatusLabel: UILabel = {
let label = UILabel()
label.adjustsFontSizeToFitWidth = true
label.font = UIFont(name: "PingFangSC-Regular", size: 15)
label.textColor = UIColor(0x888888)
label.textAlignment = .center
return label
}()
init(viewModel: RoomMessageViewModel) {
self.viewModel = viewModel
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - view layout
private var isViewReady: Bool = false
override func didMoveToWindow() {
super.didMoveToWindow()
guard !isViewReady else { return }
backgroundColor = .white
constructViewHierarchy()
activateConstraints()
bindInteraction()
isViewReady = true
}
func constructViewHierarchy() {
addSubview(roomStatusView)
roomStatusView.addSubview(roomStatusImageView)
roomStatusView.addSubview(roomStatusLabel)
roomStatusView.addSubview(roomNameLabel)
roomStatusView.addSubview(stackView)
setupUserStackView()
roomStatusView.addSubview(inviteUserButton)
addSubview(enterRoomStatusLabel)
addSubview(userNumberLabel)
addSubview(enterRoomButton)
}
func activateConstraints() {
roomStatusView.snp.makeConstraints { make in
make.top.leading.trailing.equalToSuperview()
make.height.equalTo(110)
}
roomStatusImageView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(15)
make.leading.equalToSuperview().offset(12)
}
roomStatusLabel.snp.makeConstraints { make in
make.centerY.equalTo(roomStatusImageView)
make.leading.equalTo(roomStatusImageView.snp.trailing).offset(4)
}
roomNameLabel.snp.makeConstraints { make in
make.top.equalTo(roomStatusImageView.snp.bottom).offset(9)
make.leading.equalTo(roomStatusImageView)
make.trailing.equalToSuperview().offset(-12)
}
stackView.snp.makeConstraints { make in
make.leading.equalTo(roomNameLabel)
make.bottom.equalToSuperview().offset(-4)
}
inviteUserButton.snp.makeConstraints { make in
make.leading.equalTo(stackView.snp.trailing).offset(2)
make.width.height.equalTo(24)
make.bottom.equalToSuperview().offset(-4)
}
userNumberLabel.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-10)
make.leading.equalToSuperview().offset(12)
make.width.equalTo(100)
make.height.equalTo(20)
}
enterRoomButton.snp.makeConstraints { make in
make.trailing.equalToSuperview().offset(-12)
make.bottom.equalToSuperview().offset(-10)
make.width.equalTo(70)
make.height.equalTo(27)
}
enterRoomStatusLabel.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-10)
make.centerX.equalToSuperview()
make.width.equalTo(150)
make.height.equalTo(20)
}
}
func bindInteraction() {
viewModel.viewResponder = self
enterRoomButton.addTarget(self, action: #selector(enterRoomAction(sender:)), for: .touchUpInside)
inviteUserButton.addTarget(self, action: #selector(inviteUserAction(sender:)), for: .touchUpInside)
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPressAction(sender:)))
addGestureRecognizer(longPressGesture)
layer.masksToBounds = true
layer.borderWidth = 0.5
layer.borderColor = UIColor(0xDDDDDD).cgColor
setupViewState()
}
@objc func enterRoomAction(sender: UIButton) {
viewModel.enterRoomAction()
}
@objc func inviteUserAction(sender: UIButton) {
viewModel.inviteUserAction()
}
@objc func longPressAction(sender: UIView) {
return
}
func setupViewState() {
roomNameLabel.text = (viewModel.message.ownerName ) + .quickMeetingText
if viewModel.message.owner != viewModel.userId {
inviteUserButton.isHidden = true
} else {
inviteUserButton.isHidden = false
}
switch viewModel.message.roomState {
case .creating:
roomStatusImageView.image = UIImage(named: "room_is_creating", in: tuiRoomKitBundle(), compatibleWith: nil)
roomStatusLabel.text = .meetingText
enterRoomStatusLabel.isHidden = false
enterRoomStatusLabel.text = .startingMeetingText + "..."
userNumberLabel.isHidden = true
enterRoomButton.isHidden = true
roomStatusView.backgroundColor = UIColor(0xDCEAFD)
case .created:
roomStatusImageView.image = UIImage(named: "room_created_success", in: tuiRoomKitBundle(), compatibleWith: nil)
roomStatusLabel.text = .meetingText + "." + .inProgressText
roomStatusLabel.textColor = UIColor(0x15B72D)
enterRoomButton.isHidden = false
userNumberLabel.isHidden = false
enterRoomStatusLabel.isHidden = true
if viewModel.message.memberCount > 1 {
userNumberLabel.text = String(viewModel.message.memberCount) + .peopleEnteredMeetingText
} else {
userNumberLabel.text = .waitingMembersEnterMeetingText
}
roomStatusView.backgroundColor = UIColor(0xDCEAFD)
case .destroyed:
roomStatusImageView.image = UIImage(named: "room_has_destroyed", in: tuiRoomKitBundle(), compatibleWith: nil)
roomStatusLabel.text = .meetingText
roomStatusLabel.textColor = UIColor(0x888888)
enterRoomStatusLabel.isHidden = false
enterRoomStatusLabel.text = .meetingEnded
enterRoomButton.isHidden = true
userNumberLabel.isHidden = true
roomStatusView.backgroundColor = UIColor(0xDDDDDD)
inviteUserButton.isHidden = true
default: break
}
}
func setupStackView() {
if !isViewReady {
return
}
setupUserStackView()
layoutIfNeeded()
if viewModel.message.memberCount > 1 {
userNumberLabel.text = String(viewModel.message.memberCount) + .peopleEnteredMeetingText
} else {
userNumberLabel.text = .waitingMembersEnterMeetingText
}
}
private func setupUserStackView() {
var userNumber = 0
viewArray.forEach { view in
view.removeFromSuperview()
}
viewModel.message.userList.forEach { userDic in
if userNumber >= 5 {
let label = UILabel()
label.text = "..."
viewArray.append(label)
stackView.addArrangedSubview(label)
label.snp.makeConstraints { make in
make.height.equalTo(24)
make.width.equalTo(24)
}
return
}
let placeholderImage = UIImage(named: "room_default_avatar", in: tuiRoomKitBundle(), compatibleWith: nil)
let imageView = UIImageView()
if let userAvatar = userDic["faceUrl"] as? String {
imageView.sd_setImage(with: URL(string: userAvatar), placeholderImage: placeholderImage)
} else {
imageView.image = placeholderImage
}
viewArray.append(imageView)
stackView.addArrangedSubview(imageView)
imageView.snp.makeConstraints { make in
make.height.equalTo(24)
make.width.equalTo(24)
}
userNumber = userNumber + 1
}
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let viewFrame = self.frame
let inviteViewFrame = self.inviteUserButton.frame
if viewFrame.contains(point) && !inviteViewFrame.contains(point) {
return enterRoomButton
}
return super.hitTest(point, with: event)
}
deinit {
debugPrint("deinit \(self)")
}
}
extension RoomMessageView: RoomMessageViewResponder {
func updateStackView() {
setupStackView()
}
func updateRoomStatus() {
setupViewState()
}
func changeEnterRoomButton(isEnabled: Bool) {
enterRoomButton.isEnabled = isEnabled
}
func updateEnteredRoom() {
enterRoomButton.isSelected = true
}
func updateExitRoom() {
enterRoomButton.isSelected = false
}
}
private extension String {
static var inviteMeetingText: String {
localized("Invite you to a meeting")
}
static var enterMeetingText: String {
localized("Enter the meeting")
}
static var alreadyEnteredMeeting: String {
localized("Already entered the meeting")
}
static var meetingText: String {
localized("Meeting")
}
static var inProgressText: String {
localized("Ongoing")
}
static var peopleEnteredMeetingText: String {
localized("People have entered the meeting")
}
static var startingMeetingText: String {
localized("Starting meeting")
}
static var waitingMembersEnterMeetingText: String {
localized("Waiting for members to enter the meeting")
}
static var meetingEnded: String {
localized("Meeting ended")
}
static var quickMeetingText: String {
localized("Quick meeting")
}
}

View File

@@ -0,0 +1,47 @@
//
// ChatExtensionRoomSettingsViewModel.swift
// TUIRoomKit
//
// Created by janejntang on 2023/6/26.
//
import Foundation
class ChatExtensionRoomSettingsViewModel {
var isOpenMicrophone: Bool
var isOpenCamera: Bool
private let engineManager = EngineManager.shared
private(set) var roomSettingsViewItems: [RoomSetListItemData] = []
init(isOpenMicrophone: Bool, isOpenCamera: Bool) {
self.isOpenMicrophone = isOpenMicrophone
self.isOpenCamera = isOpenCamera
createRoomSettingsModel()
}
func createRoomSettingsModel() {
let openMicItem = RoomSetListItemData()
openMicItem.titleText = .micSeatText
openMicItem.isSwitchOn = isOpenMicrophone
openMicItem.action = {[weak self] sender in
guard let self = self, let view = sender as? UISwitch else { return }
self.engineManager.store.isOpenMicrophone = view.isOn
}
roomSettingsViewItems.append(openMicItem)
let openCameraItem = RoomSetListItemData()
openCameraItem.titleText = .cameraSetText
openCameraItem.isSwitchOn = isOpenCamera
openCameraItem.action = {[weak self] sender in
guard let self = self, let view = sender as? UISwitch else { return }
self.engineManager.store.isOpenCamera = view.isOn
}
roomSettingsViewItems.append(openCameraItem)
}
}
private extension String {
static var cameraSetText: String {
localized("Join the meeting and start the camera")
}
static var micSeatText: String {
localized("Join the conference and turn on the mic")
}
}

View File

@@ -0,0 +1,95 @@
//
// RoomaInviteViewModel.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/24.
// Copyright © 2023 Tencent. All rights reserved.
//
import Foundation
import TUICore
import AVFAudio
class InvitedToJoinRoomViewModel: NSObject, AVAudioPlayerDelegate {
let inviteUserName: String
let roomId: String
var avatarUrl: String
var displayLink: CADisplayLink?
var audioPlayer: AVAudioPlayer = AVAudioPlayer()
var startTime: TimeInterval?
var endTime: TimeInterval?
var messageManager: RoomMessageManager {
return RoomMessageManager.shared
}
private var roomManager: RoomManager {
RoomManager.shared
}
init(inviteUserName: String, inviteUserAvatarUrl: String, roomId: String) {
self.inviteUserName = inviteUserName
self.roomId = roomId
avatarUrl = inviteUserAvatarUrl
super.init()
playAudio(forResource: "phone_ringing", ofType: "mp3")
}
func startPlay() {
audioPlayer.play()
}
func stopPlay() {
audioPlayer.stop()
}
func disagreeAction() {
stopPlay()
closeInvitedToJoinRoomView()
}
func agreeAction() {
stopPlay()
if EngineManager.shared.store.isEnteredRoom {
roomManager.exitOrDestroyPreviousRoom { [weak self] in
guard let self = self else { return }
self.enterRoom()
} onError: { code, message in
debugPrint("exitRoom, code:\(code), message:\(message)")
}
} else {
enterRoom()
}
}
private func enterRoom() {
roomManager.enterRoom(roomId: roomId)
closeInvitedToJoinRoomView()
}
private func playAudio(forResource: String, ofType: String){
if let bundlePath = Bundle.main.path(forResource: forResource, ofType: ofType) {
let url = URL(fileURLWithPath: bundlePath)
do {
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
} catch let error {
debugPrint("AVAudioSession set outputAudioPort error:\(error.localizedDescription)")
}
do {
try audioPlayer = AVAudioPlayer(contentsOf: url)
audioPlayer.numberOfLoops = -1
audioPlayer.delegate = self
audioPlayer.prepareToPlay()
} catch let error {
debugPrint("audioPlayer error: \(error.localizedDescription)")
}
}
}
private func closeInvitedToJoinRoomView() {
TUIRoomImAccessService.shared.inviteWindow?.isHidden = true
TUIRoomImAccessService.shared.inviteWindow = nil
TUIRoomImAccessService.shared.isShownInvitedToJoinRoomView = false
}
deinit {
debugPrint("deinit \(self)")
}
}

View File

@@ -0,0 +1,59 @@
//
// RoomMsgViewModel.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/8.
// Copyright © 2023 Tencent. All rights reserved.
//
import Foundation
import TIMCommon
import TUICore
import RTCRoomEngine
@objc(RoomMessageBubbleCellData)
class RoomMessageBubbleCellData: TUIBubbleMessageCellData {
var messageModel: RoomMessageModel?
override init(direction: TMsgDirection) {
super.init(direction: direction)
}
override class func getCellData(_ message: V2TIMMessage) -> TUIMessageCellData {
let messageModel = RoomMessageModel()
messageModel.updateMessage(message: message)
if messageModel.roomId == RoomManager.shared.roomId, messageModel.roomState != .destroyed {
RoomManager.shared.roomObserver.messageModel.updateMessage(message: message)
}
let messageCellData = RoomMessageBubbleCellData(direction: message.isSelf ? .MsgDirectionOutgoing : .MsgDirectionIncoming)
messageCellData.messageModel = messageModel
return messageCellData
}
override class func getDisplayString(_ message: V2TIMMessage) -> String {
let businessID = parseBusinessID(message: message)
if businessID == BussinessID_GroupRoomMessage {
let dict = TUITool.jsonData2Dictionary(message.customElem.data) as? [String: Any]
let userName = dict?["ownerName"] as? String ?? ""
return userName + .quickMeetingText
} else {
return super.getDisplayString(message)
}
}
private class func parseBusinessID(message: V2TIMMessage?) -> String {
guard let message = message else { return "" }
let customData = message.customElem.data
let dict = TUITool.jsonData2Dictionary(customData)
guard let businessID = dict?["businessID"] as? String else { return ""}
return businessID
}
deinit {
debugPrint("deinit \(self)")
}
}
private extension String {
static var quickMeetingText: String {
localized("'s quick meeting")
}
}

View File

@@ -0,0 +1,96 @@
//
// RoomMessageViewModel.swift
// TUIRoomKit
//
// Created by janejntang on 2023/5/10.
// Copyright © 2023 Tencent. All rights reserved.
//
import Foundation
import RTCRoomEngine
import TUICore
import TIMCommon
protocol RoomMessageViewResponder: NSObject {
func updateStackView()
func updateRoomStatus()
func updateEnteredRoom()
func updateExitRoom()
}
class RoomMessageViewModel: NSObject {
var message: RoomMessageModel
private var engineManager: EngineManager {
EngineManager.shared
}
lazy var userId: String = {
return TUILogin.getUserID() ?? EngineManager.shared.store.currentUser.userId
}()
var messageManager: RoomMessageManager {
RoomMessageManager.shared
}
let roomManager = RoomManager.shared
weak var viewResponder: RoomMessageViewResponder?
init(message: RoomMessageModel) {
self.message = message
super.init()
roomManager.roomObserver.addListener(listener: self)
}
deinit {
roomManager.roomObserver.removeListener(listener: self)
debugPrint("deinit \(self)")
}
func changeMessage(message: RoomMessageModel) {
self.message = message
viewResponder?.updateStackView()
viewResponder?.updateRoomStatus()
}
func enterRoomAction() {
guard BusinessSceneUtil.canJoinRoom() else { return }
if roomManager.isEnteredOtherRoom(roomId: message.roomId) {
roomManager.exitOrDestroyPreviousRoom { [weak self] in
guard let self = self else { return }
self.enterRoom()
} onError: { [weak self] code, message in
debugPrint("exitRoom,code:\(code),message:\(message)")
guard let self = self else { return }
self.enterRoom()
}
} else {
enterRoom()
}
}
private func enterRoom() {
if !engineManager.store.isEnteredRoom {
roomManager.enterRoom(roomId: message.roomId)
} else {
EngineEventCenter.shared.notifyUIEvent(key: .TUIRoomKitService_ShowRoomMainView, param: [:])
}
}
func inviteUserAction() {
guard message.groupId.count > 0 else { return }
let inviter = TUILoginUserInfo()
inviter.userId = userId
inviter.userName = TUILogin.getNickName() ?? ""
inviter.avatarUrl = TUILogin.getFaceUrl() ?? ""
InviteToJoinRoomManager.startInviteToJoinRoom(message: message, inviter: inviter)
}
}
extension RoomMessageViewModel: RoomObserverListener {
func onRoomEnter(messageId: String, code: Int, message: String) {
if code == 0, messageId == self.message.messageId {
viewResponder?.updateEnteredRoom()
}
}
func onRoomExit(messageId: String) {
if messageId == self.message.messageId {
viewResponder?.updateExitRoom()
}
}
}