diff --git a/NEChatUIKit/NEChatUIKit.podspec b/NEChatUIKit/NEChatUIKit.podspec index 5683b015..b6314fa1 100644 --- a/NEChatUIKit/NEChatUIKit.podspec +++ b/NEChatUIKit/NEChatUIKit.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = 'NEChatUIKit' - s.version = '9.6.1' + s.version = '9.6.3' s.summary = 'Chat Module of IM.' # This description is used to generate tags and improve search results. @@ -46,7 +46,6 @@ TODO: Add long description of the pod here. s.dependency 'NECommonUIKit' s.dependency 'NECommonKit' s.dependency 'MJRefresh' - s.dependency 'UITextView+Placeholder' s.dependency 'SDWebImageWebPCoder' s.dependency 'SDWebImageSVGKitPlugin' s.dependency 'lottie-ios','2.5.3' diff --git a/NEChatUIKit/NEChatUIKit/Classes/Base/BaseView/ChatCornerCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Base/BaseView/ChatCornerCell.swift index bc713cbd..19ad994f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Base/BaseView/ChatCornerCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Base/BaseView/ChatCornerCell.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. +import NECommonUIKit // this cell has rounding corner style import UIKit -import NECommonUIKit @objcMembers public class ChatCornerCell: CornerCell {} diff --git a/NEChatUIKit/NEChatUIKit/Classes/Base/BaseView/NEChatBaseCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Base/BaseView/NEChatBaseCell.swift index e5941978..517da2ce 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Base/BaseView/NEChatBaseCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Base/BaseView/NEChatBaseCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit +import UIKit @objcMembers open class NEChatBaseCell: UITableViewCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Base/BaseViewController/ChatBaseViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Base/BaseViewController/ChatBaseViewController.swift index 8fa4de27..d1e78844 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Base/BaseViewController/ChatBaseViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Base/BaseViewController/ChatBaseViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECommonUIKit +import NECoreKit +import UIKit @objcMembers open class ChatBaseViewController: UIViewController, UIGestureRecognizerDelegate { @@ -55,12 +55,14 @@ open class ChatBaseViewController: UIViewController, UIGestureRecognizerDelegate private func setupBackUI() { let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) - navigationItem.leftBarButtonItem = UIBarButtonItem( + let backItem = UIBarButtonItem( image: image, style: .plain, target: self, action: #selector(backEvent) ) + backItem.accessibilityIdentifier = "id.backArrow" + navigationItem.leftBarButtonItem = backItem navigationController?.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem() navigationController?.navigationBar.topItem?.backBarButtonItem?.tintColor = .ne_darkText } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Base/BaseViewController/ChatTableViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Base/BaseViewController/ChatTableViewController.swift index 2be61a95..c7af6d83 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Base/BaseViewController/ChatTableViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Base/BaseViewController/ChatTableViewController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreKit +import UIKit @objcMembers open class ChatTableViewController: NEBaseViewController, UITableViewDelegate, diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/ChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/ChatViewController.swift index 2bf134b0..2c62e46a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/ChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/ChatViewController.swift @@ -3,17 +3,17 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreIMKit -import NIMSDK -import MJRefresh import AVFoundation +import MJRefresh +import NEChatKit import NECommonKit -import NECoreKit import NECommonUIKit -import WebKit -import NEChatKit +import NECoreIMKit +import NECoreKit +import NIMSDK import Photos +import UIKit +import WebKit @objcMembers open class ChatViewController: ChatBaseViewController, UINavigationControllerDelegate, @@ -121,8 +121,19 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel weak var weakSelf = self NEChatDetectNetworkTool.shareInstance.netWorkReachability { status in - if status == .notReachable, let networkView = weakSelf?.brokenNetworkView { - weakSelf?.view.addSubview(networkView) + if status == .notReachable, + let networkView = weakSelf?.brokenNetworkView, + let self = weakSelf { + self.view.addSubview(networkView) + NSLayoutConstraint.activate([ + networkView.topAnchor.constraint( + equalTo: self.tableView.topAnchor, + constant: 0 + ), + networkView.leftAnchor.constraint(equalTo: self.view.leftAnchor), + networkView.rightAnchor.constraint(equalTo: self.view.rightAnchor), + networkView.heightAnchor.constraint(equalToConstant: self.networkToolHeight), + ]) } else { weakSelf?.brokenNetworkView.removeFromSuperview() } @@ -246,6 +257,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel let view = NEBrokenNetworkView(frame: CGRect(x: 0, y: kNavigationHeight + KStatusBarHeight, width: kScreenWidth, height: networkToolHeight)) + view.translatesAutoresizingMaskIntoConstraints = false return view }() @@ -1140,7 +1152,7 @@ open class ChatViewController: ChatBaseViewController, UINavigationControllerDel if atIndexs.isEmpty { return } - NELog.infoLog(className(), desc: "on revoke message at indexs \(atIndexs)") + operationView?.removeFromSuperview() tableViewReloadIndexs(atIndexs) } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEBaseForwardAlertViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseForwardAlertViewController.swift similarity index 96% rename from NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEBaseForwardAlertViewController.swift rename to NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseForwardAlertViewController.swift index dd11364d..8d5d2f73 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEBaseForwardAlertViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseForwardAlertViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NECommonUIKit +import UIKit @objc public class ForwardItem: NSObject { @@ -22,6 +22,7 @@ public class NEBaseForwardUserCell: UICollectionViewCell { header.translatesAutoresizingMaskIntoConstraints = false header.titleLabel.font = NEConstant.defaultTextFont(11.0) header.clipsToBounds = true + header.accessibilityIdentifier = "id.forwardHeaderView" return header }() @@ -85,6 +86,7 @@ public class NEBaseForwardAlertViewController: UIViewController, UICollectionVie let header = NEUserHeaderView(frame: .zero) header.clipsToBounds = true header.translatesAutoresizingMaskIntoConstraints = false + header.accessibilityIdentifier = "id.forwardHeaderView" return header }() @@ -102,6 +104,7 @@ public class NEBaseForwardAlertViewController: UIViewController, UICollectionVie label.font = NEConstant.defaultTextFont(14.0) label.textColor = .ne_darkText label.numberOfLines = 0 + label.accessibilityIdentifier = "id.forwardContentText" return label }() @@ -125,6 +128,7 @@ public class NEBaseForwardAlertViewController: UIViewController, UICollectionVie tip.font = NEConstant.defaultTextFont(16.0) tip.textColor = .ne_darkText tip.text = chatLocalizable("send_to") + tip.accessibilityIdentifier = "id.forwardTitle" contentView.addSubview(tip) NSLayoutConstraint.activate([ tip.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 16.0), @@ -207,11 +211,13 @@ public class NEBaseForwardAlertViewController: UIViewController, UICollectionVie canceBtn.addTarget(self, action: #selector(cancelClick), for: .touchUpInside) canceBtn.setTitle(chatLocalizable("cancel"), for: .normal) canceBtn.setTitleColor(.ne_greyText, for: .normal) + canceBtn.accessibilityIdentifier = "id.forwardCancelBtn" sureBtn.translatesAutoresizingMaskIntoConstraints = false sureBtn.addTarget(self, action: #selector(sureClick), for: .touchUpInside) sureBtn.setTitle(chatLocalizable("send"), for: .normal) sureBtn.setTitleColor(.ne_blueText, for: .normal) + sureBtn.accessibilityIdentifier = "id.forwardSendBtn" contentView.addSubview(canceBtn) NSLayoutConstraint.activate([ diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBasePinMessageViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBasePinMessageViewController.swift index 3d1cc826..906c9628 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBasePinMessageViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBasePinMessageViewController.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit let PinMessageDefaultType = 1000 diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseReadViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseReadViewController.swift index 8ee51b38..3b9a53df 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseReadViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseReadViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK -import NECoreIMKit import NECommonUIKit +import NECoreIMKit +import NIMSDK +import UIKit @objcMembers open class NEBaseReadViewController: ChatBaseViewController, UIScrollViewDelegate, UITableViewDelegate, diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseSelectUserViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseSelectUserViewController.swift index 94d00a54..2fcbf0ff 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseSelectUserViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseSelectUserViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit import NECoreIMKit +import UIKit public typealias DidSelectedAtRow = (_ index: Int, _ model: ChatTeamMemberInfoModel?) -> Void @objcMembers diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseUserSettingViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseUserSettingViewController.swift index 5aadd396..e12b0df9 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseUserSettingViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEBaseUserSettingViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class NEBaseUserSettingViewController: ChatBaseViewController, UserSettingViewModelDelegate, @@ -27,6 +27,7 @@ open class NEBaseUserSettingViewController: ChatBaseViewController, UserSettingV let button = ExpandButton() button.translatesAutoresizingMaskIntoConstraints = false button.setImage(coreLoader.loadImage("setting_add"), for: .normal) + button.accessibilityIdentifier = "id.add" return button }() @@ -36,6 +37,7 @@ open class NEBaseUserSettingViewController: ChatBaseViewController, UserSettingV label.font = NEConstant.defaultTextFont(12.0) label.textColor = .ne_darkText label.textAlignment = .center + label.accessibilityIdentifier = "id.name" return label }() @@ -244,6 +246,14 @@ open class NEBaseUserSettingViewController: ChatBaseViewController, UserSettingV for: indexPath ) as? NEBaseUserSettingCell { cell.configure(model) + if let c = cell as? UserSettingSwitchCell { + if model.cellName == chatLocalizable("message_remind") { + c.tSwitch.accessibilityIdentifier = "id.messageRemind" + } + if model.cellName == chatLocalizable("session_set_top") { + c.tSwitch.accessibilityIdentifier = "id.stickTop" + } + } return cell } return UITableViewCell() diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEDetailMapController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEDetailMapController.swift index 9af758d8..4e05cb17 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEDetailMapController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/NEDetailMapController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit import NECoreKit +import UIKit @objcMembers public class NEDetailMapController: ChatBaseViewController, NEMapGuideBottomViewDelegate { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/TextViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/TextViewController.swift index 5ecc9284..c7a2847c 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/TextViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Controller/TextViewController.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonContainerView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonContainerView.swift index 804a8813..f01e5fd8 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonContainerView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonContainerView.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objc public protocol InputEmoticonContainerViewDelegate: NSObjectProtocol { func selectedEmoticon(emoticonID: String, emotCatalogID: String, description: String) func didPressSend(sender: UIButton) @@ -210,6 +210,7 @@ extension InputEmoticonContainerView { catalogID: id, delegate: self ) + button.accessibilityIdentifier = "id.emoji" rowIndex = indexInPage / layout.columes coloumnIndex = indexInPage % layout.columes let x = coloumnIndex * Int(layout.cellWidth) + startX diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonTabView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonTabView.swift index eaa66675..f0b9f103 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonTabView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/InputEmoticonTabView.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objc public protocol InputEmoticonTabViewDelegate: NSObjectProtocol { @objc optional func tabView(_ tabView: InputEmoticonTabView?, didSelectTabIndex index: Int) } @@ -86,6 +86,7 @@ public class InputEmoticonTabView: UIControl { button.titleLabel?.textColor = .white button.backgroundColor = UIColor.ne_blueText button.titleLabel?.font = DefaultTextFont(14) + button.accessibilityIdentifier = "id.emojiSend" return button }() } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NEEmotionTool.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NEEmotionTool.swift index 0b1ec50f..85759717 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NEEmotionTool.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NEEmotionTool.swift @@ -18,7 +18,7 @@ public class NEEmotionTool: NSObject { let regularArr = reExpression?.matches( in: str, options: .reportProgress, - range: NSRange(location: 0, length: str.count) + range: NSRange(location: 0, length: str.utf16.count) ) let emoticons = NIMInputEmoticonManager.shared diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonButton.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonButton.swift index 524b4d04..be4553e0 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonButton.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonButton.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit public protocol NIMInputEmoticonButtonDelegate: NSObjectProtocol { func selectedEmoticon(emotion: NIMInputEmoticon, catalogID: String) } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonManager.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonManager.swift index 132c9ca9..1305c12b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonManager.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Emoji/NIMInputEmoticonManager.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit public enum NIMEmoticonType: NSInteger { case file = 0 case unicode diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/MessageUtils.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/MessageUtils.swift index 0c549807..97542349 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/MessageUtils.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/MessageUtils.swift @@ -4,8 +4,8 @@ // found in the LICENSE file. import Foundation -import NIMSDK import NECoreIMKit +import NIMSDK @objcMembers public class MessageUtils: NSObject { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/NotificationMessageUtils.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/NotificationMessageUtils.swift index ac420fe8..68a95e32 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/NotificationMessageUtils.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Helper/NotificationMessageUtils.swift @@ -4,9 +4,9 @@ // found in the LICENSE file. import Foundation -import NIMSDK import NECoreIMKit import NECoreKit +import NIMSDK public enum TeamType { case advanceTeam diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageAtCacheModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageAtCacheModel.swift index e793f46c..2a789cb3 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageAtCacheModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageAtCacheModel.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageAtInfoModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageAtInfoModel.swift index 2b1c91d2..97ec3da6 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageAtInfoModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageAtInfoModel.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCallRecordModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCallRecordModel.swift index 6fac26f0..05d24c96 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCallRecordModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCallRecordModel.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers class MessageCallRecordModel: MessageContentModel { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageContentModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageContentModel.swift index f22dd7c8..effad06b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageContentModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageContentModel.swift @@ -3,11 +3,11 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. +import CoreAudio import Foundation +import NECoreIMKit import NIMSDK -import CoreAudio import simd -import NECoreIMKit @objcMembers public class MessageContentModel: NSObject, MessageModel { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCustomModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCustomModel.swift index 81111fab..c9d8e843 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCustomModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageCustomModel.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objc public class MessageCustomModel: MessageContentModel { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageFileModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageFileModel.swift index 9ac8dc78..2f989053 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageFileModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageFileModel.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers class MessageFileModel: MessageContentModel { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageLocationModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageLocationModel.swift index 0898fc28..4ee29b40 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageLocationModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageLocationModel.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit class MessageLocationModel: MessageContentModel { public var lat: Double? diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageVideoModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageVideoModel.swift index 82440a82..23d57343 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageVideoModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/MessageVideoModel.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objc enum DownloadState: Int { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NECustomAttachmentProtocol.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NECustomAttachmentProtocol.swift index 00738643..f925429f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NECustomAttachmentProtocol.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NECustomAttachmentProtocol.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NEMoreItemModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NEMoreItemModel.swift index fc38231d..3d1debcf 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NEMoreItemModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/NEMoreItemModel.swift @@ -16,6 +16,8 @@ public enum NEMoreActionType: Int { case other = 100 } +@objc +@objcMembers public class NEMoreItemModel: NSObject { // 单元图标 public var image: UIImage? diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/PinMessageModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/PinMessageModel.swift index 67be26ee..d7e38c4b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/PinMessageModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/Model/PinMessageModel.swift @@ -1,18 +1,18 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK -import NECoreIMKit import NEChatKit +import NECoreIMKit +import NIMSDK +import UIKit public class PinMessageModel: NSObject { var chatmodel: MessageModel? var message: NIMMessage var item: NIMMessagePinItem var session: NIMSession - var repo = ChatRepo() + var repo = ChatRepo.shared init(message: NIMMessage, item: NIMMessagePinItem) { self.message = message diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatMessageCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatMessageCell.swift index bfe2fc26..afb25678 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatMessageCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatMessageCell.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit import NIMSDK +import UIKit @objc public protocol ChatBaseCellDelegate: NSObjectProtocol { @@ -96,12 +96,14 @@ open class NEBaseChatMessageCell: NEChatBaseCell { avatarImageLeft.clipsToBounds = true avatarImageLeft.isUserInteractionEnabled = true avatarImageLeft.contentMode = .scaleAspectFill + avatarImageLeft.accessibilityIdentifier = "id.avatar" avatarImageRight.backgroundColor = UIColor(hexString: "#537FF4") avatarImageRight.translatesAutoresizingMaskIntoConstraints = false avatarImageRight.clipsToBounds = true avatarImageRight.isUserInteractionEnabled = true avatarImageRight.contentMode = .scaleAspectFill + avatarImageRight.accessibilityIdentifier = "id.avatar" // name nameLabelLeft.textAlignment = .center @@ -118,6 +120,7 @@ open class NEBaseChatMessageCell: NEChatBaseCell { fullNameLabel.translatesAutoresizingMaskIntoConstraints = false fullNameLabel.font = UIFont.systemFont(ofSize: 12) fullNameLabel.textColor = UIColor.ne_lightText + fullNameLabel.accessibilityIdentifier = "id.fullNameLabel" // bubbleImage bubbleImageLeft.backgroundColor = NEKitChatConfig.shared.ui.receiveMessageBg diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatMessageTipCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatMessageTipCell.swift index 5f6a380b..dec78f77 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatMessageTipCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatMessageTipCell.swift @@ -42,6 +42,7 @@ open class NEBaseChatMessageTipCell: UITableViewCell { label.textColor = NEKitChatConfig.shared.ui.timeTextColor label.textAlignment = .center label.translatesAutoresizingMaskIntoConstraints = false + label.accessibilityIdentifier = "id.messageTipText" return label }() } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatTeamMemberCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatTeamMemberCell.swift index 7151fd1e..ec5223c2 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatTeamMemberCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/NEBaseChatTeamMemberCell.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECommonUIKit import NEChatKit +import NECommonUIKit +import UIKit @objcMembers open class NEBaseChatTeamMemberCell: UITableViewCell { @@ -15,6 +15,7 @@ open class NEBaseChatTeamMemberCell: UITableViewCell { header.titleLabel.textColor = UIColor.white header.clipsToBounds = true header.translatesAutoresizingMaskIntoConstraints = false + header.accessibilityIdentifier = "id.atCellHeaderView" return header }() @@ -22,6 +23,7 @@ open class NEBaseChatTeamMemberCell: UITableViewCell { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.textColor = .ne_darkText + label.accessibilityIdentifier = "id.atCellName" return label }() diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/OperationCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/OperationCell.swift index 5f7cc36c..ad08fbb3 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/OperationCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/OperationCell.swift @@ -26,6 +26,7 @@ open class OperationCell: UICollectionViewCell { imageView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(imageView) imageView.contentMode = .center + imageView.accessibilityIdentifier = "id.menuIcon" NSLayoutConstraint.activate([ imageView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor, constant: 0), imageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8), @@ -37,6 +38,7 @@ open class OperationCell: UICollectionViewCell { label.translatesAutoresizingMaskIntoConstraints = false label.textColor = UIColor.ne_darkText label.textAlignment = .center + label.accessibilityIdentifier = "id.menuTitle" contentView.addSubview(label) NSLayoutConstraint.activate([ label.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 8), diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageAudioCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageAudioCell.swift index 2bc3651a..29207e25 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageAudioCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageAudioCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageCell.swift index ec8dbf95..e7eab21f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageCell.swift @@ -1,11 +1,11 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK -import NECommonUIKit import NECommonKit +import NECommonUIKit +import NIMSDK +import UIKit @objc public protocol PinMessageCellDelegate { @@ -29,6 +29,7 @@ open class NEBasePinMessageCell: UITableViewCell { header.layer.cornerRadius = 16 header.clipsToBounds = true header.translatesAutoresizingMaskIntoConstraints = false + header.accessibilityIdentifier = "id.avatar" return header }() @@ -37,6 +38,7 @@ open class NEBasePinMessageCell: UITableViewCell { label.font = UIFont.systemFont(ofSize: 12.0) label.textColor = .ne_darkText label.translatesAutoresizingMaskIntoConstraints = false + label.accessibilityIdentifier = "id.name" return label }() @@ -111,6 +113,7 @@ open class NEBasePinMessageCell: UITableViewCell { let moreBtn = UIButton() moreBtn.addTarget(self, action: #selector(moreClick), for: .touchUpInside) + moreBtn.accessibilityIdentifier = "id.moreAction" moreBtn.translatesAutoresizingMaskIntoConstraints = false backView.addSubview(moreBtn) NSLayoutConstraint.activate([ diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageDefaultCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageDefaultCell.swift index c9e5df7b..8740a3ca 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageDefaultCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageDefaultCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageFileCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageFileCell.swift index 38a6f05e..cad66392 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageFileCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageFileCell.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class NEBasePinMessageFileCell: NEBasePinMessageCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageImageCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageImageCell.swift index 78f7e2b8..29ca04ce 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageImageCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageImageCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageLocationCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageLocationCell.swift index bf6b44ec..824913af 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageLocationCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageLocationCell.swift @@ -1,10 +1,10 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit import NECommonKit +import UIKit @objcMembers open class NEBasePinMessageLocationCell: NEBasePinMessageCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageTextCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageTextCell.swift index f8835637..161c0324 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageTextCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageTextCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageVideoCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageVideoCell.swift index a32bece2..402b8c74 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageVideoCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/PinCell/NEBasePinMessageVideoCell.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class NEBasePinMessageVideoCell: NEBasePinMessageImageCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/UserBaseTableViewCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/UserBaseTableViewCell.swift index bd9cd79d..46d6991a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/UserBaseTableViewCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/Cell/UserBaseTableViewCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class UserBaseTableViewCell: UITableViewCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatActivityIndicatorView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatActivityIndicatorView.swift index 625da261..54bb3d74 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatActivityIndicatorView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/ChatActivityIndicatorView.swift @@ -74,6 +74,7 @@ public class ChatActivityIndicatorView: UIView { button.translatesAutoresizingMaskIntoConstraints = false button.imageView?.contentMode = .center button.setBackgroundImage(UIImage.ne_imageNamed(name: "sendMessage_failed"), for: .normal) + button.accessibilityIdentifier = "id.sendMessageFailed" return button }() diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/CirleProgressView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/CirleProgressView.swift index 0b1da856..a711a9df 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/CirleProgressView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/CirleProgressView.swift @@ -40,6 +40,7 @@ public class CirleProgressView: UIView { override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .clear + accessibilityIdentifier = "id.status" imageView.frame = bounds imageView.contentMode = .center addSubview(imageView) diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/CopyableLabel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/CopyableLabel.swift index c0353db0..1ea008b1 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/CopyableLabel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/CopyableLabel.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECommonUIKit import MobileCoreServices +import NECommonUIKit +import UIKit @objcMembers open class CopyableLabel: UILabel { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEBaseChatInputView.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEBaseChatInputView.swift index 9a0a0c69..8da473d8 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEBaseChatInputView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEBaseChatInputView.swift @@ -3,10 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NECoreKit -import UITextView_Placeholder +import UIKit @objc public enum ChatMenuType: Int { @@ -36,8 +35,9 @@ open class NEBaseChatInputView: UIView, ChatRecordViewDelegate, public var nickAccidDic = [String: String]() - public var textView: UITextView = { - let textView = UITextView() + public var textView: NETextView = { + let textView = NETextView() + textView.placeholderLabel.numberOfLines = 1 textView.layer.cornerRadius = 8 textView.font = UIFont.systemFont(ofSize: 16) textView.clipsToBounds = true @@ -48,6 +48,7 @@ open class NEBaseChatInputView: UIView, ChatRecordViewDelegate, textView.typingAttributes = [NSAttributedString.Key.foregroundColor: UIColor.ne_darkText, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)] textView.linkTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.ne_darkText, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)] textView.dataDetectorTypes = [] + textView.accessibilityIdentifier = "id.chatMessageInput" return textView }() diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEInputMoreCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEInputMoreCell.swift index 76204030..564d963a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEInputMoreCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/ChatView/NEInputMoreCell.swift @@ -41,6 +41,7 @@ public class NEInputMoreCell: UICollectionViewCell { let imageView = UIImageView() imageView.isUserInteractionEnabled = true imageView.translatesAutoresizingMaskIntoConstraints = false + imageView.accessibilityIdentifier = "id.actionIcon" return imageView }() diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/MapView/NEMapAddressCell.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/MapView/NEMapAddressCell.swift index 9ee5b0e5..fd44700b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/View/MapView/NEMapAddressCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/View/MapView/NEMapAddressCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit +import UIKit @objcMembers public class NEMapAddressCell: UITableViewCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/ChatViewModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/ChatViewModel.swift index 5b78a870..2c5f68b1 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/ChatViewModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/ChatViewModel.swift @@ -3,11 +3,11 @@ // found in the LICENSE file. import Foundation -import NECoreIMKit -import NIMSDK import NEChatKit import NECommonKit +import NECoreIMKit import NECoreKit +import NIMSDK // import NEKitContact @objc @@ -55,7 +55,7 @@ public class ChatViewModel: NSObject, ChatRepoMessageDelegate, NIMChatManagerDel // 下拉时间戳 private var oldMsg: NIMMessage? - public var repo: ChatRepo = .init() + public var repo = ChatRepo.shared public var operationModel: MessageContentModel? private var userInfo = [String: User]() public var isReplying = false diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/PinMessageViewModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/PinMessageViewModel.swift index 03a080f5..1757dbe9 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/PinMessageViewModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/PinMessageViewModel.swift @@ -1,10 +1,10 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit import NIMSDK +import UIKit @objc public protocol PinMessageViewModelDelegate: NSObjectProtocol { @@ -13,7 +13,7 @@ public protocol PinMessageViewModelDelegate: NSObjectProtocol { @objcMembers public class PinMessageViewModel: NSObject, ChatExtendProviderDelegate, NIMChatManagerDelegate, NIMConversationManagerDelegate { - public let chatRepo = ChatRepo() + public let chatRepo = ChatRepo.shared public var items = [PinMessageModel]() public var delegate: PinMessageViewModelDelegate? public var session: NIMSession? diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamChatViewModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamChatViewModel.swift index 87a6473b..52a74c90 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamChatViewModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamChatViewModel.swift @@ -2,10 +2,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import Foundation -import NIMSDK import CoreText +import Foundation import NECoreIMKit +import NIMSDK @objc public protocol TeamChatViewModelDelegate: ChatViewModelDelegate { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamMemberSelectVM.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamMemberSelectVM.swift index ff78d649..4a63304d 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamMemberSelectVM.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/TeamMemberSelectVM.swift @@ -3,13 +3,13 @@ // found in the LICENSE file. import Foundation -import NIMSDK import NEChatKit import NECoreIMKit +import NIMSDK @objcMembers public class TeamMemberSelectVM: NSObject { - public var chatRepo: ChatRepo = .init() + public var chatRepo = ChatRepo.shared private let className = "TeamMemberSelectVM" public func fetchTeamMembers(sessionId: String, diff --git a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/UserSettingViewModel.swift b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/UserSettingViewModel.swift index 2c3e217b..6c3d1b62 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/UserSettingViewModel.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Chat/ViewModel/UserSettingViewModel.swift @@ -14,7 +14,7 @@ protocol UserSettingViewModelDelegate: NSObjectProtocol { @objcMembers public class UserSettingViewModel: NSObject { - var repo = ChatRepo() + var repo = ChatRepo.shared var userInfo: User? diff --git a/NEChatUIKit/NEChatUIKit/Classes/ChatConfig/ChatUIConfig.swift b/NEChatUIKit/NEChatUIKit/Classes/ChatConfig/ChatUIConfig.swift index de742d2f..830e8098 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/ChatConfig/ChatUIConfig.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/ChatConfig/ChatUIConfig.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit +import UIKit /// 头像枚举类型 @objc public enum NEChatAvatarType: Int { diff --git a/NEChatUIKit/NEChatUIKit/Classes/ChatRouter/NEBaseChatRouter.swift b/NEChatUIKit/NEChatUIKit/Classes/ChatRouter/NEBaseChatRouter.swift index 33540dd6..69b20770 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/ChatRouter/NEBaseChatRouter.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/ChatRouter/NEBaseChatRouter.swift @@ -4,11 +4,11 @@ // found in the LICENSE file. import Foundation -import NIMSDK import NECommonKit +import NIMSDK import SDWebImage -import SDWebImageWebPCoder import SDWebImageSVGKitPlugin +import SDWebImageWebPCoder @objcMembers public class ChatRouter: NSObject { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Common/ChatConstant.swift b/NEChatUIKit/NEChatUIKit/Classes/Common/ChatConstant.swift index 425d3108..2bf471bd 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Common/ChatConstant.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Common/ChatConstant.swift @@ -4,10 +4,10 @@ // found in the LICENSE file. import Foundation -@_exported import NECoreKit -@_exported import NECommonUIKit @_exported import NECommonKit +@_exported import NECommonUIKit @_exported import NECoreIMKit +@_exported import NECoreKit let coreLoader = CoreLoader() func chatLocalizable(_ key: String) -> String { diff --git a/NEChatUIKit/NEChatUIKit/Classes/Common/NEChatUIKitClient.swift b/NEChatUIKit/NEChatUIKit/Classes/Common/NEChatUIKitClient.swift index 7177b0a9..8ae7b4a4 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Common/NEChatUIKitClient.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Common/NEChatUIKitClient.swift @@ -3,9 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit +@objc @objcMembers public class NEChatUIKitClient: NSObject { public static let instance = NEChatUIKitClient() diff --git a/NEChatUIKit/NEChatUIKit/Classes/Extension/ChatImageExtension.swift b/NEChatUIKit/NEChatUIKit/Classes/Extension/ChatImageExtension.swift index ba1b992d..be05242b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Extension/ChatImageExtension.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Extension/ChatImageExtension.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import Foundation import CoreGraphics +import Foundation import UIKit public extension UIImage { class func ne_imageNamed(name: String?) -> UIImage? { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageBaseCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageBaseCell.swift index a1555c07..76e5ca33 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageBaseCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageBaseCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageFileCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageFileCell.swift index b1105e74..c9545d24 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageFileCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageFileCell.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class FunChatMessageFileCell: FunChatMessageBaseCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageImageCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageImageCell.swift index ba8c6f90..ea828db0 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageImageCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageImageCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunChatMessageImageCell: FunChatMessageBaseCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageLocationCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageLocationCell.swift index 6e93279e..e729138c 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageLocationCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageLocationCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit +import UIKit @objcMembers open class FunChatMessageLocationCell: FunChatMessageBaseCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageReplyCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageReplyCell.swift index a477f106..11b6dd7e 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageReplyCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageReplyCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageVideoCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageVideoCell.swift index 66b5efce..157f09b5 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageVideoCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatMessageVideoCell.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class FunChatMessageVideoCell: FunChatMessageImageCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatTeamMemberCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatTeamMemberCell.swift index 1737da2c..582de08b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatTeamMemberCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunChatTeamMemberCell.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECommonUIKit import NEChatKit +import NECommonUIKit +import UIKit @objcMembers open class FunChatTeamMemberCell: NEBaseChatTeamMemberCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunUserTableViewCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunUserTableViewCell.swift index 304a3111..2e4876c7 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunUserTableViewCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/FunUserTableViewCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class FunUserTableViewCell: UserBaseTableViewCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageAudioCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageAudioCell.swift index c184bcdd..582f438d 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageAudioCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageAudioCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageDefaultCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageDefaultCell.swift index 02ffcd0f..4f47fb57 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageDefaultCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageDefaultCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageFileCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageFileCell.swift index e5040709..28928b77 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageFileCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageFileCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageImageCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageImageCell.swift index 5a19b7af..9e8f6925 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageImageCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageImageCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageLocationCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageLocationCell.swift index f1406251..57e35380 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageLocationCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageLocationCell.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit +import UIKit @objcMembers open class FunPinMessageLocationCell: NEBasePinMessageLocationCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageTextCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageTextCell.swift index 666dc099..a3d7f3ed 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageTextCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageTextCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageVideoCell.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageVideoCell.swift index 858b5177..d20781c6 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageVideoCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Cell/PinCell/FunPinMessageVideoCell.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunPinMessageVideoCell: NEBasePinMessageVideoCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunChatViewController.swift index 106b76c0..11b2e500 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunChatViewController.swift @@ -1,10 +1,10 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK import NECommonKit +import NIMSDK +import UIKit @objcMembers open class FunChatViewController: ChatViewController, FunChatInputViewDelegate, NIMUserManagerDelegate, FunChatRecordViewDelegate { @@ -301,52 +301,55 @@ open class FunChatViewController: ChatViewController, FunChatInputViewDelegate, override open func showReplyMessageView(isReEdit: Bool = false) { viewmodel.isReplying = true - getFunInputView()?.showReplyMode() - if var message = viewmodel.operationModel?.message { + guard let replyView = getFunInputView() else { return } + replyView.showReplyMode() + if let message = viewmodel.operationModel?.message { if isReEdit { - if let replyMessage = viewmodel.getReplyMessageWithoutThread(message: message) as? MessageContentModel, let msg = replyMessage.message { - msg.text = message.text - message = msg + replyView.replyLabel.attributedText = NEEmotionTool.getAttWithStr(str: viewmodel.operationModel?.replyText ?? "", + font: .systemFont(ofSize: 13), + color: .ne_greyText) + if let replyMessage = viewmodel.getReplyMessageWithoutThread(message: message) as? MessageContentModel { viewmodel.operationModel = replyMessage } - } - var text = chatLocalizable("msg_reply") - if let uid = message.from { - var showName = viewmodel.getShowName(userId: uid, teamId: viewmodel.session.sessionId, false) - if viewmodel.session.sessionType != .P2P, - !IMKitClient.instance.isMySelf(uid) { - addToAtUsers(addText: "@" + showName + "", isReply: true, accid: uid) - } - let user = viewmodel.getUserInfo(userId: uid) - if let alias = user?.alias { - showName = alias + } else { + var text = chatLocalizable("msg_reply") + if let uid = message.from { + var showName = viewmodel.getShowName(userId: uid, teamId: viewmodel.session.sessionId, false) + if viewmodel.session.sessionType != .P2P, + !IMKitClient.instance.isMySelf(uid) { + addToAtUsers(addText: "@" + showName + "", isReply: true, accid: uid) + } + let user = viewmodel.getUserInfo(userId: uid) + if let alias = user?.alias { + showName = alias + } + text += " " + showName } - text += " " + showName - } - text += ": " - switch message.messageType { - case .text: - if let t = message.text { - text += t + text += ": " + switch message.messageType { + case .text: + if let t = message.text { + text += t + } + case .image: + text += "[\(chatLocalizable("msg_image"))]" + case .audio: + text += "[\(chatLocalizable("msg_audio"))]" + case .video: + text += "[\(chatLocalizable("msg_video"))]" + case .file: + text += "[\(chatLocalizable("msg_file"))]" + case .location: + text += "[\(chatLocalizable("msg_location"))]" + case .custom: + text += "[\(chatLocalizable("msg_custom"))]" + default: + text += "[\(chatLocalizable("msg_unknown"))]" } - case .image: - text += "[\(chatLocalizable("msg_image"))]" - case .audio: - text += "[\(chatLocalizable("msg_audio"))]" - case .video: - text += "[\(chatLocalizable("msg_video"))]" - case .file: - text += "[\(chatLocalizable("msg_file"))]" - case .location: - text += "[\(chatLocalizable("msg_location"))]" - case .custom: - text += "[\(chatLocalizable("msg_custom"))]" - default: - text += "[\(chatLocalizable("msg_unknown"))]" + replyView.replyLabel.attributedText = NEEmotionTool.getAttWithStr(str: text, + font: .systemFont(ofSize: 13), + color: .ne_greyText) } - getFunInputView()?.replyLabel.attributedText = NEEmotionTool.getAttWithStr(str: text, - font: .systemFont(ofSize: 13), - color: .ne_greyText) if menuView.textView.isFirstResponder { normalOffset = -10 layoutInputView(offset: currentKeyboardHeight) diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunForwardAlertViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunForwardAlertViewController.swift index dcd38067..e7baeaae 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunForwardAlertViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunForwardAlertViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NECommonUIKit +import UIKit @objcMembers public class FunForwardUserCell: NEBaseForwardUserCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunGroupChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunGroupChatViewController.swift index 22043247..033e9340 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunGroupChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunGroupChatViewController.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunGroupChatViewController: FunChatViewController, TeamChatViewModelDelegate { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunP2PChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunP2PChatViewController.swift index 741bd190..a4851ebe 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunP2PChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunP2PChatViewController.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunP2PChatViewController: FunChatViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunPinMessageViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunPinMessageViewController.swift index de03efa2..db921385 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunPinMessageViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunPinMessageViewController.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunPinMessageViewController: NEBasePinMessageViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunReadViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunReadViewController.swift index bb71de57..122a58a6 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunReadViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunReadViewController.swift @@ -2,10 +2,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK -import NECoreIMKit import NECommonUIKit +import NECoreIMKit +import NIMSDK +import UIKit @objcMembers open class FunReadViewController: NEBaseReadViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunSelectUserViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunSelectUserViewController.swift index 4d81ca14..d02183e8 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunSelectUserViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunSelectUserViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit import NECoreIMKit +import UIKit @objcMembers open class FunSelectUserViewController: NEBaseSelectUserViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunUserSettingViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunUserSettingViewController.swift index b6bd9822..9f81eac0 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunUserSettingViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/Controller/FunUserSettingViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class FunUserSettingViewController: NEBaseUserSettingViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/FunChatUIColor.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/FunChatUIColor.swift index d80cbede..88f81456 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/FunChatUIColor.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/FunChatUIColor.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/View/FunChatInputView.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/View/FunChatInputView.swift index 36fa2529..80e94f83 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/View/FunChatInputView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/View/FunChatInputView.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/FunUI/View/FunRecordAudioView.swift b/NEChatUIKit/NEChatUIKit/Classes/FunUI/View/FunRecordAudioView.swift index a8a8524b..5c66cc9f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/FunUI/View/FunRecordAudioView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/FunUI/View/FunRecordAudioView.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import Lottie +import UIKit @objc public protocol FunChatRecordViewDelegate: NSObjectProtocol { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageAudioCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageAudioCell.swift index 07b46670..4948d4d4 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageAudioCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageAudioCell.swift @@ -33,6 +33,7 @@ open class ChatMessageAudioCell: NormalChatMessageBaseCell, ChatAudioCellProtoco open func commonUILeft() { audioImageViewLeft.contentMode = .center audioImageViewLeft.translatesAutoresizingMaskIntoConstraints = false + audioImageViewLeft.accessibilityIdentifier = "id.animation" bubbleImageLeft.addSubview(audioImageViewLeft) NSLayoutConstraint.activate([ audioImageViewLeft.leftAnchor.constraint(equalTo: bubbleImageLeft.leftAnchor, constant: 16), @@ -45,6 +46,7 @@ open class ChatMessageAudioCell: NormalChatMessageBaseCell, ChatAudioCellProtoco timeLabelLeft.textColor = UIColor.ne_darkText timeLabelLeft.textAlignment = .left timeLabelLeft.translatesAutoresizingMaskIntoConstraints = false + timeLabelLeft.accessibilityIdentifier = "id.time" bubbleImageLeft.addSubview(timeLabelLeft) NSLayoutConstraint.activate([ timeLabelLeft.leftAnchor.constraint(equalTo: audioImageViewLeft.rightAnchor, constant: 12), @@ -63,6 +65,7 @@ open class ChatMessageAudioCell: NormalChatMessageBaseCell, ChatAudioCellProtoco open func commonUIRight() { audioImageViewRight.contentMode = .center audioImageViewRight.translatesAutoresizingMaskIntoConstraints = false + audioImageViewRight.accessibilityIdentifier = "id.animation" bubbleImageRight.addSubview(audioImageViewRight) NSLayoutConstraint.activate([ audioImageViewRight.rightAnchor.constraint(equalTo: bubbleImageRight.rightAnchor, constant: -16), @@ -75,6 +78,7 @@ open class ChatMessageAudioCell: NormalChatMessageBaseCell, ChatAudioCellProtoco timeLabelRight.textColor = UIColor.ne_darkText timeLabelRight.textAlignment = .right timeLabelRight.translatesAutoresizingMaskIntoConstraints = false + timeLabelRight.accessibilityIdentifier = "id.time" bubbleImageRight.addSubview(timeLabelRight) NSLayoutConstraint.activate([ timeLabelRight.rightAnchor.constraint(equalTo: audioImageViewRight.leftAnchor, constant: -12), diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageCallCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageCallCell.swift index 68c8c570..d86b189e 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageCallCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageCallCell.swift @@ -30,6 +30,7 @@ open class ChatMessageCallCell: NormalChatMessageBaseCell { contentLabelLeft.font = NEKitChatConfig.shared.ui.messageTextSize contentLabelLeft.textAlignment = .center contentLabelLeft.backgroundColor = .clear + contentLabelLeft.accessibilityIdentifier = "id.chatMessageCallText" bubbleImageLeft.addSubview(contentLabelLeft) NSLayoutConstraint.activate([ contentLabelLeft.rightAnchor.constraint(equalTo: bubbleImageLeft.rightAnchor, constant: -chat_content_margin), @@ -47,6 +48,7 @@ open class ChatMessageCallCell: NormalChatMessageBaseCell { contentLabelRight.font = NEKitChatConfig.shared.ui.messageTextSize contentLabelRight.textAlignment = .center contentLabelRight.backgroundColor = .clear + contentLabelRight.accessibilityIdentifier = "id.chatMessageCallText" bubbleImageRight.addSubview(contentLabelRight) NSLayoutConstraint.activate([ contentLabelRight.rightAnchor.constraint(equalTo: bubbleImageRight.rightAnchor, constant: -chat_content_margin), diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageFileCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageFileCell.swift index 24e4971c..361cdc24 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageFileCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageFileCell.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class ChatMessageFileCell: NormalChatMessageBaseCell { @@ -15,6 +15,7 @@ open class ChatMessageFileCell: NormalChatMessageBaseCell { let view_img = UIImageView() view_img.translatesAutoresizingMaskIntoConstraints = false view_img.backgroundColor = .clear + view_img.accessibilityIdentifier = "id.fileType" return view_img }() @@ -33,6 +34,7 @@ open class ChatMessageFileCell: NormalChatMessageBaseCell { label.lineBreakMode = .byTruncatingMiddle label.font = DefaultTextFont(14) label.textAlignment = .left + label.accessibilityIdentifier = "id.displayName" return label }() @@ -42,6 +44,7 @@ open class ChatMessageFileCell: NormalChatMessageBaseCell { label.textColor = UIColor(hexString: "#999999") label.font = NEConstant.defaultTextFont(10.0) label.textAlignment = .left + label.accessibilityIdentifier = "id.displaySize" return label }() @@ -70,6 +73,7 @@ open class ChatMessageFileCell: NormalChatMessageBaseCell { let view_img = UIImageView() view_img.translatesAutoresizingMaskIntoConstraints = false view_img.backgroundColor = .clear + view_img.accessibilityIdentifier = "id.fileType" return view_img }() @@ -88,6 +92,7 @@ open class ChatMessageFileCell: NormalChatMessageBaseCell { label.lineBreakMode = .byTruncatingMiddle label.font = DefaultTextFont(14) label.textAlignment = .left + label.accessibilityIdentifier = "id.displayName" return label }() @@ -97,6 +102,7 @@ open class ChatMessageFileCell: NormalChatMessageBaseCell { label.textColor = UIColor(hexString: "#999999") label.font = NEConstant.defaultTextFont(10.0) label.textAlignment = .left + label.accessibilityIdentifier = "id.displaySize" return label }() diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageImageCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageImageCell.swift index 63dacc68..2f01c523 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageImageCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageImageCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class ChatMessageImageCell: NormalChatMessageBaseCell { @@ -28,6 +28,7 @@ open class ChatMessageImageCell: NormalChatMessageBaseCell { contentImageViewLeft.translatesAutoresizingMaskIntoConstraints = false contentImageViewLeft.contentMode = .scaleAspectFill contentImageViewLeft.clipsToBounds = true + contentImageViewLeft.accessibilityIdentifier = "id.thumbnail" contentImageViewLeft.addCustomCorner( conrners: [.bottomLeft, .bottomRight, .topRight], radius: 8, @@ -48,12 +49,13 @@ open class ChatMessageImageCell: NormalChatMessageBaseCell { open func commonUIRight() { contentImageViewRight.translatesAutoresizingMaskIntoConstraints = false contentImageViewRight.contentMode = .scaleAspectFill + contentImageViewRight.clipsToBounds = true + contentImageViewRight.accessibilityIdentifier = "id.thumbnail" contentImageViewRight.addCustomCorner( conrners: [.topLeft, .bottomLeft, .bottomRight], radius: 8, backcolor: .white ) - contentImageViewRight.clipsToBounds = true bubbleImageRight.addSubview(contentImageViewRight) NSLayoutConstraint.activate([ diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageLocationCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageLocationCell.swift index dcd1f9fe..dfe0b813 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageLocationCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageLocationCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit +import UIKit @objcMembers open class ChatMessageLocationCell: NormalChatMessageBaseCell { @@ -12,6 +12,7 @@ open class ChatMessageLocationCell: NormalChatMessageBaseCell { label.translatesAutoresizingMaskIntoConstraints = false label.textColor = UIColor.ne_darkText label.font = UIFont.systemFont(ofSize: 16.0) + label.accessibilityIdentifier = "id.locationItemTitle" return label }() @@ -20,6 +21,7 @@ open class ChatMessageLocationCell: NormalChatMessageBaseCell { label.translatesAutoresizingMaskIntoConstraints = false label.textColor = UIColor.ne_lightText label.font = UIFont.systemFont(ofSize: 12.0) + label.accessibilityIdentifier = "id.locationItemAddress" return label }() @@ -42,6 +44,7 @@ open class ChatMessageLocationCell: NormalChatMessageBaseCell { label.translatesAutoresizingMaskIntoConstraints = false label.textColor = UIColor.ne_darkText label.font = UIFont.systemFont(ofSize: 16.0) + label.accessibilityIdentifier = "id.locationItemTitle" return label }() @@ -50,6 +53,7 @@ open class ChatMessageLocationCell: NormalChatMessageBaseCell { label.translatesAutoresizingMaskIntoConstraints = false label.textColor = UIColor.ne_lightText label.font = UIFont.systemFont(ofSize: 12.0) + label.accessibilityIdentifier = "id.locationItemAddress" return label }() diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageTextCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageTextCell.swift index 418b811c..72ac2ebe 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageTextCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageTextCell.swift @@ -16,6 +16,7 @@ open class ChatMessageTextCell: NormalChatMessageBaseCell { label.font = NEKitChatConfig.shared.ui.messageTextSize label.backgroundColor = .clear label.textAlignment = .justified + label.accessibilityIdentifier = "id.messageText" return label }() @@ -28,6 +29,7 @@ open class ChatMessageTextCell: NormalChatMessageBaseCell { label.font = NEKitChatConfig.shared.ui.messageTextSize label.backgroundColor = .clear label.textAlignment = .justified + label.accessibilityIdentifier = "id.messageText" return label }() diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageVideoCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageVideoCell.swift index d482ebb8..5cf8151c 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageVideoCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatMessageVideoCell.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class ChatMessageVideoCell: ChatMessageImageCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatTeamMemberCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatTeamMemberCell.swift index 985e7915..3bfe8bc4 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatTeamMemberCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/ChatTeamMemberCell.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECommonUIKit import NEChatKit +import NECommonUIKit +import UIKit @objcMembers open class ChatTeamMemberCell: NEBaseChatTeamMemberCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/NormalChatMessageBaseCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/NormalChatMessageBaseCell.swift index 1b6e44de..a3a3890b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/NormalChatMessageBaseCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/NormalChatMessageBaseCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageAudioCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageAudioCell.swift index 57c8677e..aaa4e1a1 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageAudioCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageAudioCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageDefaultCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageDefaultCell.swift index 4366a21f..4337eff0 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageDefaultCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageDefaultCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageFileCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageFileCell.swift index 6bc41a1c..3e92cc08 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageFileCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageFileCell.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class PinMessageFileCell: NEBasePinMessageFileCell {} diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageImageCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageImageCell.swift index b3477ff7..159a9bac 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageImageCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageImageCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageLocationCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageLocationCell.swift index 285b57d3..752994d8 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageLocationCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageLocationCell.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit +import UIKit @objcMembers open class PinMessageLocationCell: NEBasePinMessageLocationCell {} diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageTextCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageTextCell.swift index 96c3b646..683efd8b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageTextCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageTextCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageVideoCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageVideoCell.swift index 48c81dfb..f0a6728b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageVideoCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/PinCell/PinMessageVideoCell.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class PinMessageVideoCell: NEBasePinMessageVideoCell {} diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/UserTableViewCell.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/UserTableViewCell.swift index 2b42a23a..d9f5a332 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/UserTableViewCell.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Cell/UserTableViewCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class UserTableViewCell: UserBaseTableViewCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/ForwardAlertViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/ForwardAlertViewController.swift index 2d433230..77e904b0 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/ForwardAlertViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/ForwardAlertViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NECommonUIKit +import UIKit @objcMembers public class ForwardUserCell: NEBaseForwardUserCell { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/GroupChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/GroupChatViewController.swift index faf1f650..67cc161f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/GroupChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/GroupChatViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK import NECoreIMKit +import NIMSDK +import UIKit @objcMembers open class GroupChatViewController: NormalChatViewController, TeamChatViewModelDelegate { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/NormalChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/NormalChatViewController.swift index 8d014315..adf87c48 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/NormalChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/NormalChatViewController.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class NormalChatViewController: ChatViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/P2PChatViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/P2PChatViewController.swift index 5e1bff6e..6604c061 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/P2PChatViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/P2PChatViewController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class P2PChatViewController: NormalChatViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/PinMessageViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/PinMessageViewController.swift index 1b97e1eb..5b8a3b5b 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/PinMessageViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/PinMessageViewController.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class PinMessageViewController: NEBasePinMessageViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/ReadViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/ReadViewController.swift index 1b5ec91c..2b7e5d87 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/ReadViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/ReadViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK -import NECoreIMKit import NECommonUIKit +import NECoreIMKit +import NIMSDK +import UIKit @objcMembers open class ReadViewController: NEBaseReadViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/SelectUserViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/SelectUserViewController.swift index 35257338..896ab813 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/SelectUserViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/SelectUserViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NEChatKit import NECoreIMKit +import UIKit @objcMembers open class SelectUserViewController: NEBaseSelectUserViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/UserSettingViewController.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/UserSettingViewController.swift index 0044488e..0cfa964f 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/UserSettingViewController.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/Controller/UserSettingViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class UserSettingViewController: NEBaseUserSettingViewController { diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/NormalChatUIColor.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/NormalChatUIColor.swift index 307d5f9e..33195f89 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/NormalChatUIColor.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/NormalChatUIColor.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/View/ChatInpuView.swift b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/View/ChatInpuView.swift index 54ad16a9..72c4217a 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/NormalUI/View/ChatInpuView.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/NormalUI/View/ChatInpuView.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. @@ -31,6 +31,7 @@ open class ChatInputView: NEBaseChatInputView { button.translatesAutoresizingMaskIntoConstraints = false button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) button.tag = i + 5 + button.accessibilityIdentifier = "id.chatMessageActionItemBtn" items.append(button) } diff --git a/NEChatUIKit/NEChatUIKit/Classes/Protocol/ChatInputViewDelegate.swift b/NEChatUIKit/NEChatUIKit/Classes/Protocol/ChatInputViewDelegate.swift index fcaa46a4..4adcef46 100644 --- a/NEChatUIKit/NEChatUIKit/Classes/Protocol/ChatInputViewDelegate.swift +++ b/NEChatUIKit/NEChatUIKit/Classes/Protocol/ChatInputViewDelegate.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEContactUIKit/NEContactUIKit.podspec b/NEContactUIKit/NEContactUIKit.podspec index 9994fff5..73561da7 100644 --- a/NEContactUIKit/NEContactUIKit.podspec +++ b/NEContactUIKit/NEContactUIKit.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NEContactUIKit' - s.version = '9.6.1' + s.version = '9.6.3' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. diff --git a/NEContactUIKit/NEContactUIKit/Classes/Base/NEBaseContactViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Base/NEBaseContactViewCell.swift index 2245ffd2..9926d17e 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Base/NEBaseContactViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Base/NEBaseContactViewCell.swift @@ -14,6 +14,7 @@ open class NEBaseContactViewCell: UITableViewCell { avatar.clipsToBounds = true avatar.contentMode = .scaleAspectFill avatar.backgroundColor = UIColor.colorWithNumber(number: 0) + avatar.accessibilityIdentifier = "id.avatar" NSLayoutConstraint.activate([ nameLabel.leftAnchor.constraint(equalTo: avatar.leftAnchor, constant: 1), nameLabel.rightAnchor.constraint(equalTo: avatar.rightAnchor, constant: -1), @@ -53,6 +54,7 @@ open class NEBaseContactViewCell: UITableViewCell { label.translatesAutoresizingMaskIntoConstraints = false label.font = UIFont.systemFont(ofSize: 14.0) label.textColor = UIColor(hexString: "333333") + label.accessibilityIdentifier = "id.name" return label }() @@ -62,6 +64,7 @@ open class NEBaseContactViewCell: UITableViewCell { label.translatesAutoresizingMaskIntoConstraints = false label.font = UIFont.systemFont(ofSize: 14.0) label.textColor = UIColor(hexString: "333333") + label.accessibilityIdentifier = "id.action" return label }() diff --git a/NEContactUIKit/NEContactUIKit/Classes/BlackList/Cell/NEBaseBlackListCell.swift b/NEContactUIKit/NEContactUIKit/Classes/BlackList/Cell/NEBaseBlackListCell.swift index 8d084099..7290e1f1 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/BlackList/Cell/NEBaseBlackListCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/BlackList/Cell/NEBaseBlackListCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objc protocol BlackListCellDelegate: AnyObject { @@ -34,6 +34,7 @@ open class NEBaseBlackListCell: NEBaseTeamTableViewCell { button.clipsToBounds = true button.addTarget(self, action: #selector(buttonEvent), for: .touchUpInside) button.setTitle(localizable("remove_black"), for: .normal) + button.accessibilityIdentifier = "id.relieve" contentView.addSubview(button) NSLayoutConstraint.activate([ button.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20), diff --git a/NEContactUIKit/NEContactUIKit/Classes/BlackList/ViewController/NEBaseBlackListViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/BlackList/ViewController/NEBaseBlackListViewController.swift index c4d7f411..a62cb6ce 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/BlackList/ViewController/NEBaseBlackListViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/BlackList/ViewController/NEBaseBlackListViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit -import NECoreIMKit import NECommonKit +import NECoreIMKit +import NECoreKit +import UIKit @objcMembers open class NEBaseBlackListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, @@ -36,19 +36,24 @@ open class NEBaseBlackListViewController: UIViewController, UITableViewDelegate, title = localizable("blacklist") customNavigationView.navTitle.text = title let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) - navigationItem.leftBarButtonItem = UIBarButtonItem( + let backItem = UIBarButtonItem( image: image, style: .plain, target: self, action: #selector(backEvent) ) + backItem.accessibilityIdentifier = "id.backArrow" + navigationItem.leftBarButtonItem = backItem + let addImage = UIImage.ne_imageNamed(name: "add")?.withRenderingMode(.alwaysOriginal) - navigationItem.rightBarButtonItem = UIBarButtonItem( + let addItem = UIBarButtonItem( image: addImage, style: .plain, target: self, action: #selector(addBlack) ) + addItem.accessibilityIdentifier = "id.threePoint" + navigationItem.rightBarButtonItem = addItem customNavigationView.translatesAutoresizingMaskIntoConstraints = false customNavigationView.addBackButtonTarget(target: self, selector: #selector(backEvent)) @@ -81,6 +86,7 @@ open class NEBaseBlackListViewController: UIViewController, UITableViewDelegate, contentLabel.text = localizable("black_tip") contentLabel.textColor = UIColor.ne_emptyTitleColor contentLabel.font = UIFont.systemFont(ofSize: 14) + contentLabel.accessibilityIdentifier = "id.tips" headView.addSubview(contentLabel) tableView.tableHeaderView = headView } diff --git a/NEContactUIKit/NEContactUIKit/Classes/BlackList/ViewModel/BlackListViewModel.swift b/NEContactUIKit/NEContactUIKit/Classes/BlackList/ViewModel/BlackListViewModel.swift index 8fe019cb..92a760a8 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/BlackList/ViewModel/BlackListViewModel.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/BlackList/ViewModel/BlackListViewModel.swift @@ -4,12 +4,12 @@ import Foundation import NEChatKit -import NECoreKit import NECoreIMKit +import NECoreKit @objcMembers public class BlackListViewModel: NSObject, FriendProviderDelegate { - var contactRepo = ContactRepo() + var contactRepo = ContactRepo.shared public weak var delegate: FriendProviderDelegate? private let className = "BlackListViewModel" diff --git a/NEContactUIKit/NEContactUIKit/Classes/Common/ContactConst.swift b/NEContactUIKit/NEContactUIKit/Classes/Common/ContactConst.swift index f11b86fc..a14f82b5 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Common/ContactConst.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Common/ContactConst.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import Foundation import CoreText +import Foundation import NECoreKit @objc diff --git a/NEContactUIKit/NEContactUIKit/Classes/Common/NEBaseContactRouter.swift b/NEContactUIKit/NEContactUIKit/Classes/Common/NEBaseContactRouter.swift index 5987373f..057af4b5 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Common/NEBaseContactRouter.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Common/NEBaseContactRouter.swift @@ -4,8 +4,8 @@ // found in the LICENSE file. import Foundation -import NECoreKit import NECoreIMKit +import NECoreKit import NIMSDK @objcMembers diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunBlackListCell.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunBlackListCell.swift index 3f96e17b..afc57415 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunBlackListCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunBlackListCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers class FunBlackListCell: NEBaseBlackListCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunContactTableViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunContactTableViewCell.swift index 08199f6c..418625bd 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunContactTableViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunContactTableViewCell.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreIMKit import Foundation +import NECoreIMKit import NECoreKit +import UIKit @objcMembers open class FunContactTableViewCell: NEBaseContactTableViewCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunContactUnCheckCell.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunContactUnCheckCell.swift index 9cf0e0f8..2050b4eb 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunContactUnCheckCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunContactUnCheckCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit +import UIKit @objcMembers open class FunContactUnCheckCell: NEBaseContactUnCheckCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunSystemNotificationCell.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunSystemNotificationCell.swift index 3537b336..78a23e22 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunSystemNotificationCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunSystemNotificationCell.swift @@ -3,11 +3,11 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECommonUIKit import NECoreIMKit +import NECoreKit import NIMSDK +import UIKit @objcMembers open class FunSystemNotificationCell: NEBaseSystemNotificationCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunTeamTableViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunTeamTableViewCell.swift index d3360f04..5b940dfe 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunTeamTableViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/Cell/FunTeamTableViewCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class FunTeamTableViewCell: NEBaseTeamTableViewCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/FunContactRouter.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/FunContactRouter.swift index 92982b32..de54d386 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/FunContactRouter.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/FunContactRouter.swift @@ -4,8 +4,8 @@ // found in the LICENSE file. import Foundation -import NECoreKit import NECoreIMKit +import NECoreKit import NIMSDK public extension ContactRouter { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/FunContactUIColor.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/FunContactUIColor.swift index 7bdfe155..de33e8ef 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/FunContactUIColor.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/FunContactUIColor.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/View/FunUserInfoHeaderView.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/View/FunUserInfoHeaderView.swift index d523928c..e06be1f8 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/View/FunUserInfoHeaderView.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/View/FunUserInfoHeaderView.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class FunUserInfoHeaderView: NEBaseUserInfoHeaderView { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunBlackListViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunBlackListViewController.swift index 647f69b3..1e10cadc 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunBlackListViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunBlackListViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit -import NECoreIMKit import NECommonKit +import NECoreIMKit +import NECoreKit +import UIKit @objcMembers open class FunBlackListViewController: NEBaseBlackListViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactRemakNameViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactRemakNameViewController.swift index 62a3bbca..7d919774 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactRemakNameViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactRemakNameViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit +import UIKit @objcMembers open class FunContactRemakNameViewController: NEBaseContactRemakNameViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactUserViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactUserViewController.swift index 585d5b08..650bec76 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactUserViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactUserViewController.swift @@ -2,10 +2,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class FunContactUserViewController: NEBaseContactUserViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactsSelectedViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactsSelectedViewController.swift index 7fbbb572..c6d53d1f 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactsSelectedViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactsSelectedViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class FunContactsSelectedViewController: NEBaseContactsSelectedViewController { @@ -19,6 +19,7 @@ open class FunContactsSelectedViewController: NEBaseContactsSelectedViewControll } override open func setupUI() { + collectionBackViewTopMargin = 12 super.setupUI() emptyView.setEmptyImage(name: "fun_user_empty") collectionBackView.backgroundColor = .white diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactsViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactsViewController.swift index 1e0dc824..2deb6ac9 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactsViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunContactsViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit +import UIKit @objcMembers open class FunContactsViewController: NEBaseContactsViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunFindFriendViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunFindFriendViewController.swift index ad176480..384eaf2d 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunFindFriendViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunFindFriendViewController.swift @@ -1,10 +1,10 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECoreIMKit +import NECoreKit +import UIKit @objc open class FunFindFriendViewController: NEBaseFindFriendViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunTeamListViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunTeamListViewController.swift index 262830d8..b7c5ef7c 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunTeamListViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunTeamListViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK import NECoreKit +import NIMSDK +import UIKit @objcMembers open class FunTeamListViewController: NEBaseTeamListViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunValidationMessageViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunValidationMessageViewController.swift index b688062e..9b38c77f 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunValidationMessageViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/FunUI/ViewController/FunValidationMessageViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECoreIMKit +import NECoreKit +import UIKit @objcMembers open class FunValidationMessageViewController: NEBaseValidationMessageViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/Model/ContactInfo.swift b/NEContactUIKit/NEContactUIKit/Classes/Model/ContactInfo.swift index 79bf6531..5504ed86 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Model/ContactInfo.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Model/ContactInfo.swift @@ -5,8 +5,8 @@ import Foundation import NECoreIMKit -import UIKit import NECoreKit +import UIKit @objcMembers open class ContactInfo: NSObject { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/BlackListCell.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/BlackListCell.swift index 02102774..073bd43e 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/BlackListCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/BlackListCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class BlackListCell: NEBaseBlackListCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/ContactTableViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/ContactTableViewCell.swift index 695d358b..954fd8f4 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/ContactTableViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/ContactTableViewCell.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreIMKit import Foundation +import NECoreIMKit import NECoreKit +import UIKit @objcMembers open class ContactTableViewCell: NEBaseContactTableViewCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/ContactUnCheckCell.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/ContactUnCheckCell.swift index a89767db..f7950ca4 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/ContactUnCheckCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/ContactUnCheckCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit +import UIKit @objcMembers open class ContactUnCheckCell: NEBaseContactUnCheckCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/SystemNotificationCell.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/SystemNotificationCell.swift index 43b7b04a..e01d5f87 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/SystemNotificationCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/SystemNotificationCell.swift @@ -3,11 +3,11 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECommonUIKit import NECoreIMKit +import NECoreKit import NIMSDK +import UIKit @objcMembers open class SystemNotificationCell: NEBaseSystemNotificationCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/TeamTableViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/TeamTableViewCell.swift index acedd184..1157c9d2 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/TeamTableViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/Cell/TeamTableViewCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class TeamTableViewCell: NEBaseTeamTableViewCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/NromalContactRouter.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/NromalContactRouter.swift index cd48bfb1..38433150 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/NromalContactRouter.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/NromalContactRouter.swift @@ -4,8 +4,8 @@ // found in the LICENSE file. import Foundation -import NECoreKit import NECoreIMKit +import NECoreKit import NIMSDK public extension ContactRouter { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/View/UserInfoHeaderView.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/View/UserInfoHeaderView.swift index 823f4d63..b3efc216 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/View/UserInfoHeaderView.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/View/UserInfoHeaderView.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class UserInfoHeaderView: NEBaseUserInfoHeaderView { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/BlackListViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/BlackListViewController.swift index 2f961197..bf8ded50 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/BlackListViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/BlackListViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit -import NECoreIMKit import NECommonKit +import NECoreIMKit +import NECoreKit +import UIKit @objcMembers open class BlackListViewController: NEBaseBlackListViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactRemakNameViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactRemakNameViewController.swift index a411c57f..b40957d5 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactRemakNameViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactRemakNameViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit +import UIKit @objcMembers open class ContactRemakNameViewController: NEBaseContactRemakNameViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactUserViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactUserViewController.swift index 69b2858a..afb59116 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactUserViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactUserViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class ContactUserViewController: NEBaseContactUserViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactsSelectedViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactsSelectedViewController.swift index b968baed..298c8805 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactsSelectedViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactsSelectedViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class ContactsSelectedViewController: NEBaseContactsSelectedViewController { @@ -22,8 +22,6 @@ open class ContactsSelectedViewController: NEBaseContactsSelectedViewController override open func setupUI() { super.setupUI() - collectionBackViewTopMargin = 0 - collectionBackViewTopAnchor?.constant = topConstant collection.register( ContactUnCheckCell.self, diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactsViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactsViewController.swift index a5266679..438d8a9f 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactsViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ContactsViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit +import UIKit @objcMembers open class ContactsViewController: NEBaseContactsViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/FindFriendViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/FindFriendViewController.swift index 3b7a1121..b4e2a2b8 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/FindFriendViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/FindFriendViewController.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/TeamListViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/TeamListViewController.swift index a2e391c4..50d0be12 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/TeamListViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/TeamListViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK import NECoreKit +import NIMSDK +import UIKit @objcMembers open class TeamListViewController: NEBaseTeamListViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ValidationMessageViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ValidationMessageViewController.swift index d188b12c..8432d477 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ValidationMessageViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/NormalUI/ViewController/ValidationMessageViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECoreIMKit +import NECoreKit +import UIKit @objcMembers open class ValidationMessageViewController: NEBaseValidationMessageViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/Team/Cell/NEBaseTeamTableViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Team/Cell/NEBaseTeamTableViewCell.swift index 29134e22..609446eb 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Team/Cell/NEBaseTeamTableViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Team/Cell/NEBaseTeamTableViewCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class NEBaseTeamTableViewCell: UITableViewCell { @@ -26,6 +26,7 @@ open class NEBaseTeamTableViewCell: UITableViewCell { avatarImage.translatesAutoresizingMaskIntoConstraints = false avatarImage.clipsToBounds = true avatarImage.contentMode = .scaleAspectFill + avatarImage.accessibilityIdentifier = "id.avatar" contentView.addSubview(avatarImage) NSLayoutConstraint.activate([ avatarImage.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20), @@ -47,6 +48,7 @@ open class NEBaseTeamTableViewCell: UITableViewCell { ]) titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.accessibilityIdentifier = "id.name" contentView.addSubview(titleLabel) NSLayoutConstraint.activate([ titleLabel.leftAnchor.constraint(equalTo: avatarImage.rightAnchor, constant: 12), diff --git a/NEContactUIKit/NEContactUIKit/Classes/Team/ViewController/NEBaseTeamListViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Team/ViewController/NEBaseTeamListViewController.swift index 7cc16cad..db875289 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Team/ViewController/NEBaseTeamListViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Team/ViewController/NEBaseTeamListViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK import NECoreKit +import NIMSDK +import UIKit @objcMembers open class NEBaseTeamListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate { @@ -36,12 +36,15 @@ open class NEBaseTeamListViewController: UIViewController, UITableViewDelegate, title = localizable("mine_groupchat") customNavigationView.navTitle.text = title let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) - navigationItem.leftBarButtonItem = UIBarButtonItem( + let backItem = UIBarButtonItem( image: image, style: .plain, target: self, action: #selector(backEvent) ) + backItem.accessibilityIdentifier = "id.backArrow" + + navigationItem.leftBarButtonItem = backItem customNavigationView.translatesAutoresizingMaskIntoConstraints = false customNavigationView.addBackButtonTarget(target: self, selector: #selector(backEvent)) diff --git a/NEContactUIKit/NEContactUIKit/Classes/Team/ViewModel/TeamListViewModel.swift b/NEContactUIKit/NEContactUIKit/Classes/Team/ViewModel/TeamListViewModel.swift index 980053fd..03d0f459 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Team/ViewModel/TeamListViewModel.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Team/ViewModel/TeamListViewModel.swift @@ -4,12 +4,12 @@ import Foundation import NEChatKit -import NECoreKit import NECoreIMKit +import NECoreKit @objcMembers public class TeamListViewModel: NSObject, NIMTeamManagerDelegate { - var contactRepo = ContactRepo() + var contactRepo = ContactRepo.shared var refresh: () -> Void = {} public var teamList = [Team]() private let className = "TeamListViewModel" diff --git a/NEContactUIKit/NEContactUIKit/Classes/Validation/Controller/NEBaseValidationMessageViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Validation/Controller/NEBaseValidationMessageViewController.swift index 334e21de..264c22f6 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Validation/Controller/NEBaseValidationMessageViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Validation/Controller/NEBaseValidationMessageViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECoreIMKit +import NECoreKit +import UIKit @objcMembers open class NEBaseValidationMessageViewController: NEBaseContactViewController { diff --git a/NEContactUIKit/NEContactUIKit/Classes/Validation/ViewModel/ValidationMessageViewModel.swift b/NEContactUIKit/NEContactUIKit/Classes/Validation/ViewModel/ValidationMessageViewModel.swift index dab28fec..a85ab45b 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Validation/ViewModel/ValidationMessageViewModel.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Validation/ViewModel/ValidationMessageViewModel.swift @@ -13,7 +13,7 @@ public class ValidationMessageViewModel: NSObject, ContactRepoSystemNotiDelegate var dataRefresh: DataRefresh? private let className = "ValidationMessageViewModel" - let contactRepo = ContactRepo() + let contactRepo = ContactRepo.shared var datas = [XNotification]() override init() { diff --git a/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/NEBaseSystemNotificationCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/NEBaseSystemNotificationCell.swift index 093389b6..577d3c24 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/NEBaseSystemNotificationCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/NEBaseSystemNotificationCell.swift @@ -3,11 +3,11 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECommonUIKit import NECoreIMKit +import NECoreKit import NIMSDK +import UIKit @objcMembers open class NEBaseSystemNotificationCell: NEBaseValidationCell { @@ -135,6 +135,7 @@ open class NEBaseSystemNotificationCell: NEBaseValidationCell { button.layer.cornerRadius = 4 button.layer.borderColor = UIColor(hexString: "D9D9D9").cgColor button.layer.borderWidth = 1 + button.accessibilityIdentifier = "id.reject" return button }() @@ -149,6 +150,7 @@ open class NEBaseSystemNotificationCell: NEBaseValidationCell { button.layer.cornerRadius = 4 button.layer.borderWidth = 1 button.layer.borderColor = blue.cgColor + button.accessibilityIdentifier = "id.accept" return button }() @@ -165,6 +167,7 @@ open class NEBaseSystemNotificationCell: NEBaseValidationCell { label.textColor = UIColor(hexString: "B3B7BC") label.font = UIFont.systemFont(ofSize: 14.0) label.textAlignment = .right + label.accessibilityIdentifier = "id.verifyResult" return label }() diff --git a/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/NEBaseValidationCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/NEBaseValidationCell.swift index 58efc226..d932a19e 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/NEBaseValidationCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Validation/Views/NEBaseValidationCell.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NIMSDK +import UIKit public protocol SystemNotificationCellDelegate: AnyObject { func onAccept(_ notifiModel: XNotification) diff --git a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactUserViewModel.swift b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactUserViewModel.swift index 4d2ea531..e13150e0 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactUserViewModel.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactUserViewModel.swift @@ -2,15 +2,15 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. +import CoreMedia import Foundation import NEChatKit -import NECoreKit import NECoreIMKit -import CoreMedia +import NECoreKit @objcMembers public class ContactUserViewModel: NSObject { - let contactRepo = ContactRepo() + let contactRepo = ContactRepo.shared private let className = "ContactUserViewModel" func addFriend(_ account: String, _ completion: @escaping (NSError?) -> Void) { diff --git a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactViewModel.swift b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactViewModel.swift index 0a308e95..e7be32c9 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactViewModel.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/ContactViewModel.swift @@ -4,8 +4,8 @@ import Foundation import NEChatKit -import NECoreKit import NECoreIMKit +import NECoreKit import UIKit @objcMembers @@ -14,7 +14,7 @@ public class ContactViewModel: NSObject, ContactRepoSystemNotiDelegate { public var contacts: [ContactSection] = [] public var indexs: [String]? private var contactHeaders: [ContactHeadItem]? - public var contactRepo = ContactRepo() + public var contactRepo = ContactRepo.shared private var initalDict = [String: [ContactInfo]]() private let className = "ContactViewModel" diff --git a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/FindFriendViewModel.swift b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/FindFriendViewModel.swift index 0adbdc00..3f1f5eb4 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/ViewModel/FindFriendViewModel.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/ViewModel/FindFriendViewModel.swift @@ -4,12 +4,12 @@ import Foundation import NEChatKit -import NECoreKit import NECoreIMKit +import NECoreKit @objcMembers public class FindFriendViewModel: NSObject { - let contactRepo = ContactRepo() + let contactRepo = ContactRepo.shared private let className = "FindFriendViewModel" func searchFriend(_ text: String, _ completion: @escaping ([User]?, NSError?) -> Void) { diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactSelectedCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactSelectedCell.swift index a0068eaf..cb8e2180 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactSelectedCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactSelectedCell.swift @@ -27,6 +27,7 @@ open class NEBaseContactSelectedCell: NEBaseContactTableViewCell { contentView.addSubview(sImage) sImage.image = UIImage.ne_imageNamed(name: "unselect") sImage.translatesAutoresizingMaskIntoConstraints = false + sImage.accessibilityIdentifier = "id.selector" } override public func setModel(_ model: ContactInfo) { diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactTableViewCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactTableViewCell.swift index 8cb25674..e049d2df 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactTableViewCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactTableViewCell.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreIMKit import Foundation +import NECoreIMKit import NECoreKit +import UIKit @objcMembers open class NEBaseContactTableViewCell: NEBaseContactViewCell, ContactCellDataProtrol { @@ -14,6 +14,7 @@ open class NEBaseContactTableViewCell: NEBaseContactViewCell, ContactCellDataPro let imageView = UIImageView(image: UIImage.ne_imageNamed(name: "arrowRight")) imageView.translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .center + imageView.accessibilityIdentifier = "id.arrow" return imageView }() diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactUnCheckCell.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactUnCheckCell.swift index fe95169d..8f60c979 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactUnCheckCell.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/Cell/NEBaseContactUnCheckCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit +import UIKit @objcMembers open class NEBaseContactUnCheckCell: UICollectionViewCell { diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactRemakNameViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactRemakNameViewController.swift index 76470bcf..8a2715b8 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactRemakNameViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactRemakNameViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit +import UIKit @objcMembers open class NEBaseContactRemakNameViewController: NEBaseContactViewController, UITextFieldDelegate { @@ -27,6 +27,10 @@ open class NEBaseContactRemakNameViewController: NEBaseContactViewController, UI textField.delegate = self textField.clearButtonMode = .always textField.addTarget(self, action: #selector(textFieldChange), for: .editingChanged) + if let clearButton = textField.value(forKey: "_clearButton") as? UIButton { + clearButton.accessibilityIdentifier = "id.clear" + } + textField.accessibilityIdentifier = "id.editText" return textField }() diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactUserViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactUserViewController.swift index 06c368f5..7a39d028 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactUserViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactUserViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class NEBaseContactUserViewController: NEBaseContactViewController, UITableViewDelegate, @@ -205,8 +205,18 @@ open class NEBaseContactUserViewController: NEBaseContactViewController, UITable c.titleLabel.text = item.title c.detailTitleLabel.text = item.detailTitle if item.title == localizable("sign") { + c.detailTitleLabel.accessibilityIdentifier = "id.signature" c.detailTitleLabel.numberOfLines = 2 } + if item.title == localizable("email") { + c.detailTitleLabel.accessibilityIdentifier = "id.email" + } + if item.title == localizable("phone") { + c.detailTitleLabel.accessibilityIdentifier = "id.phone" + } + if item.title == localizable("birthday") { + c.detailTitleLabel.accessibilityIdentifier = "id.birthday" + } return c } @@ -216,6 +226,7 @@ open class NEBaseContactUserViewController: NEBaseContactViewController, UITable c.block = { [weak self] title, value in print("title:\(title) value\(value)") if title == localizable("add_blackList") { + c.switchButton.accessibilityIdentifier = "id.blackList" self?.blackList(isBlack: value) { c.switchButton.isOn = !c.switchButton.isOn } @@ -228,6 +239,15 @@ open class NEBaseContactUserViewController: NEBaseContactViewController, UITable if let c = cell as? CenterTextCell { c.titleLabel.text = item.title c.titleLabel.textColor = item.textColor + if item.title == localizable("chat") { + c.titleLabel.accessibilityIdentifier = "id.chat" + } + if item.title == localizable("delete_friend") { + c.titleLabel.accessibilityIdentifier = "id.delete" + } + if item.title == localizable("add_friend") { + c.titleLabel.accessibilityIdentifier = "id.chat" + } return c } return cell @@ -375,11 +395,13 @@ open class NEBaseContactUserViewController: NEBaseContactViewController, UITable } open func deleteFriend(user: User?) { + let alertTitle = localizable("delete_title").replacingOccurrences(of: "XXX", with: user?.showName(true) ?? "") let alertController = UIAlertController( - title: localizable("delete_title").replacingOccurrences(of: "XXX", with: user?.showName(true) ?? ""), + title: alertTitle, message: nil, preferredStyle: .actionSheet ) + alertController.getUILabel(string: alertTitle)?.accessibilityIdentifier = "id.title" let cancelAction = UIAlertAction( title: commonLocalizable("cancel"), @@ -387,12 +409,14 @@ open class NEBaseContactUserViewController: NEBaseContactViewController, UITable handler: nil ) cancelAction.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") + cancelAction.accessibilityIdentifier = "id.negative" let deleteAction = UIAlertAction(title: localizable("delete_friend"), style: .default) { [weak self] action in self?.deleteFriendAction(user: user) } deleteAction.setValue(UIColor.ne_redText, forKey: "_titleTextColor") + deleteAction.accessibilityIdentifier = "id.positive" alertController.addAction(cancelAction) alertController.addAction(deleteAction) diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactViewController.swift index 8e8654f2..4ef8cde6 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactViewController.swift @@ -58,6 +58,7 @@ open class NEBaseContactViewController: UIViewController, UIGestureRecognizerDel target: self, action: #selector(backToPrevious) ) + backItem.accessibilityIdentifier = "id.backArrow" backItem.tintColor = UIColor(hexString: "333333") navigationItem.leftBarButtonItem = backItem } diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactsSelectedViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactsSelectedViewController.swift index 1c333472..b21a4cb6 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactsSelectedViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactsSelectedViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class NEBaseContactsSelectedViewController: NEBaseContactViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITableViewDelegate, UITableViewDataSource { @@ -25,6 +25,7 @@ open class NEBaseContactsSelectedViewController: NEBaseContactViewController, UI view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = .clear view.layer.cornerRadius = 4 + view.isHidden = true return view }() @@ -35,15 +36,14 @@ open class NEBaseContactsSelectedViewController: NEBaseContactViewController, UI layout.minimumInteritemSpacing = 0 let collect = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) collect.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5) + collect.accessibilityIdentifier = "id.selected" return collect }() public var sureBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 76, height: 32)) - var collectionBackViewTopMargin: CGFloat = 12 - var collectionBackViewTopAnchor: NSLayoutConstraint? + var collectionBackViewTopMargin: CGFloat = 0 var collectionBackViewHeight: CGFloat = 52 - var collectionBackViewHeightAnchor: NSLayoutConstraint? public var customCells = [Int: NEBaseContactTableViewCell.Type]() // custom ui cell @@ -61,6 +61,7 @@ open class NEBaseContactsSelectedViewController: NEBaseContactViewController, UI if #available(iOS 15.0, *) { table.sectionHeaderTopPadding = 0 } + return table }() @@ -87,21 +88,19 @@ open class NEBaseContactsSelectedViewController: NEBaseContactViewController, UI open func setupUI() { view.addSubview(collectionBackView) - collectionBackViewTopAnchor = collectionBackView.topAnchor.constraint(equalTo: view.topAnchor, constant: topConstant + collectionBackViewTopMargin) - collectionBackViewHeightAnchor = collectionBackView.heightAnchor.constraint(equalToConstant: 0) NSLayoutConstraint.activate([ - collectionBackViewTopAnchor!, + collectionBackView.topAnchor.constraint(equalTo: view.topAnchor, constant: topConstant + collectionBackViewTopMargin), collectionBackView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 16), collectionBackView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -16), - collectionBackViewHeightAnchor!, + collectionBackView.heightAnchor.constraint(equalToConstant: collectionBackViewHeight), ]) - view.addSubview(collection) collection.backgroundColor = .clear collection.delegate = self collection.dataSource = self collection.allowsMultipleSelection = false collection.translatesAutoresizingMaskIntoConstraints = false + collectionBackView.addSubview(collection) NSLayoutConstraint.activate([ collection.centerYAnchor.constraint(equalTo: collectionBackView.centerYAnchor), collection.leftAnchor.constraint(equalTo: collectionBackView.leftAnchor), @@ -308,8 +307,8 @@ open class NEBaseContactsSelectedViewController: NEBaseContactViewController, UI contact === c }) == false { selectArray.append(contact) - if let height = collectionBackViewHeightAnchor?.constant, height <= 0 { - collectionBackViewHeightAnchor?.constant = collectionBackViewHeight + if collectionBackView.isHidden { + collectionBackView.isHidden = false tableViewTopAnchor?.constant += collectionBackViewHeight + collectionBackViewTopMargin * 2 } } @@ -324,8 +323,7 @@ open class NEBaseContactsSelectedViewController: NEBaseContactViewController, UI contact === c } if selectArray.count <= 0 { - collection.reloadData() - collectionBackViewHeightAnchor?.constant = 0 + collectionBackView.isHidden = true tableViewTopAnchor?.constant -= collectionBackViewHeight + collectionBackViewTopMargin * 2 } collection.reloadData() diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactsViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactsViewController.swift index 40cc383c..c17cec88 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactsViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseContactsViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit import NECoreKit +import UIKit @objc public protocol ContactsViewControllerDelegate { @@ -234,6 +234,8 @@ open class NEBaseContactsViewController: UIViewController, UITableViewDelegate, open func onNotificationUnreadCountChanged(count: Int) { print("unread count:\(count)") + viewModel.unreadCount = count + tableView.reloadData() } // MARK: FriendProviderDelegate diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseFindFriendViewController.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseFindFriendViewController.swift index f80df012..a9ecd6b3 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseFindFriendViewController.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseFindFriendViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NECoreKit import NECoreIMKit +import NECoreKit +import UIKit @objcMembers open class NEBaseFindFriendViewController: NEBaseContactViewController, UITextFieldDelegate { @@ -60,6 +60,10 @@ open class NEBaseFindFriendViewController: NEBaseContactViewController, UITextFi searchInput.returnKeyType = .search searchInput.delegate = self searchInput.clearButtonMode = .always + if let clearButton = searchInput.value(forKey: "_clearButton") as? UIButton { + clearButton.accessibilityIdentifier = "id.clear" + } + searchInput.accessibilityIdentifier = "id.addFriendAccount" NotificationCenter.default.addObserver( self, diff --git a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseUserInfoHeaderView.swift b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseUserInfoHeaderView.swift index 31b0d863..8f84d9ee 100644 --- a/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseUserInfoHeaderView.swift +++ b/NEContactUIKit/NEContactUIKit/Classes/Views/NEBaseUserInfoHeaderView.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreIMKit +import UIKit @objcMembers open class NEBaseUserInfoHeaderView: UIView { @@ -15,6 +15,7 @@ open class NEBaseUserInfoHeaderView: UIView { avatarImage.translatesAutoresizingMaskIntoConstraints = false avatarImage.contentMode = .scaleAspectFill avatarImage.clipsToBounds = true + avatarImage.accessibilityIdentifier = "id.avatar" return avatarImage }() @@ -32,6 +33,7 @@ open class NEBaseUserInfoHeaderView: UIView { titleLabel.translatesAutoresizingMaskIntoConstraints = false titleLabel.font = UIFont.boldSystemFont(ofSize: 22) titleLabel.textColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0) + titleLabel.accessibilityIdentifier = "id.name" return titleLabel }() @@ -40,6 +42,7 @@ open class NEBaseUserInfoHeaderView: UIView { detailLabel.translatesAutoresizingMaskIntoConstraints = false detailLabel.font = UIFont.systemFont(ofSize: 16) detailLabel.textColor = .ne_greyText + detailLabel.accessibilityIdentifier = "id.account" return detailLabel }() @@ -48,6 +51,7 @@ open class NEBaseUserInfoHeaderView: UIView { detailLabel.translatesAutoresizingMaskIntoConstraints = false detailLabel.font = UIFont.systemFont(ofSize: 16) detailLabel.textColor = .ne_greyText + detailLabel.accessibilityIdentifier = "id.commentName" return detailLabel }() diff --git a/NEConversationUIKit/NEConversationUIKit.podspec b/NEConversationUIKit/NEConversationUIKit.podspec index f61228d9..4fb23742 100644 --- a/NEConversationUIKit/NEConversationUIKit.podspec +++ b/NEConversationUIKit/NEConversationUIKit.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NEConversationUIKit' - s.version = '9.6.1' + s.version = '9.6.3' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Common/ConversationUI.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Common/ConversationUI.swift index 648369f1..2b66118b 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Common/ConversationUI.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Common/ConversationUI.swift @@ -5,9 +5,9 @@ import Foundation +@_exported import NEChatKit @_exported import NECommonKit @_exported import NECommonUIKit -@_exported import NEChatKit -@_exported import NIMSDK -@_exported import NECoreKit @_exported import NECoreIMKit +@_exported import NECoreKit +@_exported import NIMSDK diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Cell/NEBaseConversationListCell.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Cell/NEBaseConversationListCell.swift index 2b569775..32864a84 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Cell/NEBaseConversationListCell.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Cell/NEBaseConversationListCell.swift @@ -3,14 +3,14 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class NEBaseConversationListCell: UITableViewCell { // private var viewModel = ConversationViewModel() public var topStickInfos = [NIMSession: NIMStickTopSessionInfo]() - private let repo = ConversationRepo() + private let repo = ConversationRepo.shared private var timeWidth: NSLayoutConstraint? override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { @@ -190,6 +190,7 @@ open class NEBaseConversationListCell: UITableViewCell { return headView }() + // 单条会话未读数 public lazy var redAngleView: RedAngleLabel = { let label = RedAngleLabel() label.translatesAutoresizingMaskIntoConstraints = false @@ -204,37 +205,45 @@ open class NEBaseConversationListCell: UITableViewCell { return label }() + // 会话列表会话名称 public lazy var title: UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.textColor = NEKitConversationConfig.shared.ui.titleColor label.font = NEKitConversationConfig.shared.ui.titleFont ?? UIFont.systemFont(ofSize: 16) label.text = "Oliver" + label.accessibilityIdentifier = "id.name" return label }() + // 会话列表外露消息 public lazy var subTitle: UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.textColor = NEKitConversationConfig.shared.ui.subTitleColor label.font = NEKitConversationConfig.shared.ui.subTitleFont + label.accessibilityIdentifier = "id.message" return label }() + // 会话列表显示时间 public lazy var timeLabel: UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.textColor = NEKitConversationConfig.shared.ui.timeColor label.font = NEKitConversationConfig.shared.ui.timeFont label.textAlignment = .right + label.accessibilityIdentifier = "id.time" return label }() + // 免打扰icon public lazy var notifyMsg: UIImageView = { let notify = UIImageView() notify.translatesAutoresizingMaskIntoConstraints = false notify.image = UIImage.ne_imageNamed(name: "noNeed_notify") notify.isHidden = true + notify.accessibilityIdentifier = "id.mute" return notify }() } diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationController.swift index c811a6fd..0c003176 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class NEBaseConversationController: UIViewController, NIMChatManagerDelegate { @@ -30,6 +30,7 @@ open class NEBaseConversationController: UIViewController, NIMChatManagerDelegat func initSystemNav() { let brandBarBtn = UIButton() + brandBarBtn.accessibilityIdentifier = "id.titleBarTitle" brandBarBtn.setTitle(localizable("appName"), for: .normal) brandBarBtn.setImage(UIImage.ne_imageNamed(name: "brand_yunxin"), for: .normal) brandBarBtn.layoutButtonImage(style: .left, space: 12) diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationListViewController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationListViewController.swift index 51296cf7..d587eb73 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationListViewController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationListViewController.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objc public protocol ConversationListViewControllerDelegate { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationNavigationController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationNavigationController.swift index d66ad2c2..786a070d 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationNavigationController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationNavigationController.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreKit +import UIKit @objcMembers open class NEBaseConversationNavigationController: UIViewController, UIGestureRecognizerDelegate { @@ -47,12 +47,15 @@ open class NEBaseConversationNavigationController: UIViewController, UIGestureRe open func setupBackUI() { let image = UIImage.ne_imageNamed(name: "backArrow")?.withRenderingMode(.alwaysOriginal) - navigationItem.leftBarButtonItem = UIBarButtonItem( + let backItem = UIBarButtonItem( image: image, style: .plain, target: self, action: #selector(backEvent) ) + backItem.accessibilityIdentifier = "id.backArrow" + + navigationItem.leftBarButtonItem = backItem } open func backEvent() { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationSearchController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationSearchController.swift index 63af2702..ae04522f 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationSearchController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBaseConversationSearchController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class NEBaseConversationSearchController: NEBaseConversationNavigationController, UITableViewDelegate, @@ -111,6 +111,10 @@ open class NEBaseConversationSearchController: NEBaseConversationNavigationContr textField.returnKeyType = .search textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingChanged) textField.placeholder = localizable("search") + if let clearButton = textField.value(forKey: "_clearButton") as? UIButton { + clearButton.accessibilityIdentifier = "id.clear" + } + textField.accessibilityIdentifier = "id.search" return textField }() diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBasePopListViewController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBasePopListViewController.swift index 0d688337..508af45b 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBasePopListViewController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/Controller/NEBasePopListViewController.swift @@ -4,8 +4,8 @@ // found in the LICENSE file. import Foundation -import UIKit import NECommonKit +import UIKit @objcMembers open class PopListItem: NSObject { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationSearchViewModel.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationSearchViewModel.swift index d408787a..9e924ebd 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationSearchViewModel.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationSearchViewModel.swift @@ -2,12 +2,12 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers public class ConversationSearchViewModel: NSObject { - let repo = ConversationRepo() + let repo = ConversationRepo.shared public var searchResult: ( friend: [ConversationSearchListModel], contactGroup: [ConversationSearchListModel], diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationViewModel.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationViewModel.swift index bc740892..b1386211 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationViewModel.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Conversation/ViewModel/ConversationViewModel.swift @@ -24,7 +24,7 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, public var stickTopInfos = [NIMSession: NIMStickTopSessionInfo]() public weak var delegate: ConversationViewModelDelegate? private let className = "ConversationViewModel" - public let repo = ConversationRepo() + public let repo = ConversationRepo.shared var cacheUpdateSessionDic = [String: NIMRecentSession]() var cacheAddSessionDic = [String: ConversationListModel]() @@ -103,6 +103,7 @@ public class ConversationViewModel: NSObject, ConversationRepoDelegate, weak var weakSelf = self let option = NIMDeleteRecentSessionOption() option.isDeleteRoamMessage = true + option.shouldMarkAllMessagesReadInSessions = true repo.deleteRecentConversation(recentSession, option) { error in weakSelf?.repo.deleteLocalSession(recentSession: recentSession) } diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Cell/FunConversationListCell.swift b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Cell/FunConversationListCell.swift index 9d499b73..d140cbac 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Cell/FunConversationListCell.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Cell/FunConversationListCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunConversationListCell: NEBaseConversationListCell { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationController.swift index 436c3be3..be5b371a 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationController.swift @@ -2,10 +2,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class FunConversationController: NEBaseConversationController { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationListViewController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationListViewController.swift index 211ad1cd..b4385fde 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationListViewController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationListViewController.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunConversationListViewController: NEBaseConversationListViewController { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationSearchController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationSearchController.swift index 2d405825..add9cd6a 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationSearchController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunConversationSearchController.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunConversationSearchController: NEBaseConversationSearchController { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunPopListViewController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunPopListViewController.swift index 48db6966..80635773 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunPopListViewController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/Controller/FunPopListViewController.swift @@ -4,8 +4,8 @@ // found in the LICENSE file. import Foundation -import UIKit import NECommonKit +import UIKit @objcMembers open class FunPopListViewController: NEBasePopListViewController { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/FunConversationUIColor.swift b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/FunConversationUIColor.swift index 14a39f79..db74c392 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/FunConversationUIColor.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/FunUI/FunConversationUIColor.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/Manager/NEAtMessageManager.swift b/NEConversationUIKit/NEConversationUIKit/Classes/Manager/NEAtMessageManager.swift index cc56de0b..18e5ecec 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/Manager/NEAtMessageManager.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/Manager/NEAtMessageManager.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Cell/ConversationListCell.swift b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Cell/ConversationListCell.swift index 2beb0ac8..0741aa0d 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Cell/ConversationListCell.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Cell/ConversationListCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class ConversationListCell: NEBaseConversationListCell { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationController.swift index 24f0b511..604818ef 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NECoreKit import NIMSDK +import UIKit @objcMembers open class ConversationController: NEBaseConversationController { @@ -27,11 +27,13 @@ open class ConversationController: NEBaseConversationController { override func initSystemNav() { super.initSystemNav() let searchBarButton = UIButton() + searchBarButton.accessibilityIdentifier = "id.titleBarSearchImg" searchBarButton.setImage(UIImage.ne_imageNamed(name: "chat_search"), for: .normal) searchBarButton.addTarget(self, action: #selector(searchAction), for: .touchUpInside) let searchBarItem = UIBarButtonItem(customView: searchBarButton) let addBarButton = UIButton() + addBarButton.accessibilityIdentifier = "id.titleBarMoreImg" addBarButton.setImage(UIImage.ne_imageNamed(name: "chat_add"), for: .normal) addBarButton.addTarget(self, action: #selector(didClickAddBtn), for: .touchUpInside) let addBarItem = UIBarButtonItem(customView: addBarButton) diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationListViewController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationListViewController.swift index 41473c01..8ddf255e 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationListViewController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationListViewController.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class ConversationListViewController: NEBaseConversationListViewController { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationSearchController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationSearchController.swift index e1240c5a..306db513 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationSearchController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/ConversationSearchController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class SearchSessionHeaderView: SearchSessionBaseView { diff --git a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/PopListViewController.swift b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/PopListViewController.swift index 4103159c..43a17611 100644 --- a/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/PopListViewController.swift +++ b/NEConversationUIKit/NEConversationUIKit/Classes/NormalUI/Controller/PopListViewController.swift @@ -4,8 +4,8 @@ // found in the LICENSE file. import Foundation -import UIKit import NECommonKit +import UIKit @objcMembers open class PopListViewController: NEBasePopListViewController { diff --git a/NEMapKit/NEMapKit.podspec b/NEMapKit/NEMapKit.podspec index a92bbc1b..796d53c8 100644 --- a/NEMapKit/NEMapKit.podspec +++ b/NEMapKit/NEMapKit.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'NEMapKit' - s.version = '9.6.0' + s.version = '9.6.3' s.summary = 'Netease XKit' # This description is used to generate tags and improve search results. diff --git a/NERtcCallUIKit/NERtcCallUIKit.podspec b/NERtcCallUIKit/NERtcCallUIKit.podspec index 1ede11cc..d333e1af 100644 --- a/NERtcCallUIKit/NERtcCallUIKit.podspec +++ b/NERtcCallUIKit/NERtcCallUIKit.podspec @@ -8,43 +8,54 @@ Pod::Spec.new do |s| s.name = 'NERtcCallUIKit' - s.version = '1.8.2' + s.version = '2.2.0' s.summary = 'Netease XKit' + s.homepage = 'http://netease.im' + s.license = { :'type' => "Copyright", :'text' => " Copyright 2022 Netease " } + s.author = 'yunxin engineering department' + s.ios.deployment_target = '10.0' + s.source = { :http => "" } + s.source_files = 'NERtcCallUIKit/Classes/**/*' + s.resource = 'NERtcCallUIKit/Assets/**/*' -# This description is used to generate tags and improve search results. -# * Think: What does it do? Why did you write it? What is the focus? -# * Try to keep it short, snappy and to the point. -# * Write the description between the DESC delimiters below. -# * Finally, don't worry about the indent, CocoaPods strips it! + s.subspec 'NOS' do |nos| + nos.dependency 'NERtcCallKit/NOS','2.2.0' + nos.dependency 'SDWebImage' + nos.dependency 'NECoreKit','9.6.4' + nos.dependency 'NECommonKit' + nos.dependency 'NECommonUIKit' + nos.dependency 'NERtcSDK' + end - s.description = <<-DESC -TODO: Add long description of the pod here. - DESC + s.subspec 'NOS_Special' do |nos| + nos.dependency 'NERtcCallKit/NOS_Special', "2.2.0" + nos.dependency 'SDWebImage' + nos.dependency 'NECoreKit','9.6.4' + nos.dependency 'NECommonKit' + nos.dependency 'NECommonUIKit' + nos.dependency 'NERtcSDK' - s.homepage = 'http://netease.im' - # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' - s.license = { :'type' => 'Copyright', :'text' => ' Copyright 2022 Netease ' } - s.author = "yunxin engineering department" - s.source = { :git => 'ssh://git@g.hz.netease.com:22222/yunxin-app/xkit-ios.git', :tag => s.version.to_s } - # s.social_media_url = 'https://twitter.com/' + end - s.ios.deployment_target = '9.0' + s.subspec 'FCS' do |fcs| + fcs.dependency 'NERtcCallKit/FCS','2.2.0' + fcs.dependency 'SDWebImage' + fcs.dependency 'NECoreKit','9.6.4' + fcs.dependency 'NECommonKit' + fcs.dependency 'NECommonUIKit' + fcs.dependency 'NERtcSDK' + + end + + s.subspec 'FCS_Special' do |fcs| + fcs.dependency 'NERtcCallKit/FCS_Special', "2.2.0" + fcs.dependency 'SDWebImage' + fcs.dependency 'NECoreKit','9.6.4' + fcs.dependency 'NECommonKit' + fcs.dependency 'NECommonUIKit' + fcs.dependency 'NERtcSDK' + + end + s.default_subspecs = 'NOS' - s.source_files = 'NERtcCallUIKit/Classes/**/*' - s.resource = 'NERtcCallUIKit/Assets/**/*' - - s.dependency 'NERtcSDK' - s.dependency 'NERtcCallKit' - s.dependency 'AFNetworking' - s.dependency 'SDWebImage' - s.dependency 'Toast' - s.dependency 'NECoreKit' - s.dependency 'NECommonKit' - # s.resource_bundles = { - # 'NERtcCallUIKit' => ['NERtcCallUIKit/Assets/*.png'] - # } - - # s.public_header_files = 'Pod/Classes/**/*.h' - # s.frameworks = 'UIKit', 'MapKit' - # s.dependency 'AFNetworking', '~> 2.3' end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/Contents.json new file mode 100644 index 00000000..184d1bc3 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "phone_image@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "phone_image@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/phone_image@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/phone_image@2x.png new file mode 100644 index 00000000..54e07063 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/phone_image@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/phone_image@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/phone_image@3x.png new file mode 100644 index 00000000..7aaf74c6 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/phone_image.imageset/phone_image@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Contents.json new file mode 100644 index 00000000..34787e25 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Group 1825@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Group 1825@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Group 1825@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Group 1825@2x.png new file mode 100644 index 00000000..d3cda534 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Group 1825@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Group 1825@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Group 1825@3x.png new file mode 100644 index 00000000..53762123 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/small_button.imageset/Group 1825@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/Contents.json new file mode 100644 index 00000000..2c4a26fd --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "virtual_background_off@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "virtual_background_off@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/virtual_background_off@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/virtual_background_off@2x.png new file mode 100644 index 00000000..f0548c96 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/virtual_background_off@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/virtual_background_off@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/virtual_background_off@3x.png new file mode 100644 index 00000000..54e80ce5 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_off.imageset/virtual_background_off@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/Contents.json b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/Contents.json new file mode 100644 index 00000000..927e4eea --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "virtual_background_on@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "virtual_background_on@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/virtual_background_on@2x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/virtual_background_on@2x.png new file mode 100644 index 00000000..e14dfb3f Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/virtual_background_on@2x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/virtual_background_on@3x.png b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/virtual_background_on@3x.png new file mode 100644 index 00000000..d37ae8ba Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/NERtcCallUIKit.xcassets/virtual_background_on.imageset/virtual_background_on@3x.png differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_connecting.mp3 b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_connecting.mp3 new file mode 100644 index 00000000..35d94838 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_connecting.mp3 differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_no_response.mp3 b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_no_response.mp3 new file mode 100644 index 00000000..27ac2f7a Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_no_response.mp3 differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_peer_busy.mp3 b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_peer_busy.mp3 new file mode 100644 index 00000000..4841f71f Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_peer_busy.mp3 differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_peer_reject.mp3 b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_peer_reject.mp3 new file mode 100644 index 00000000..d6621501 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_peer_reject.mp3 differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_ring.mp3 b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_ring.mp3 new file mode 100644 index 00000000..fe16a857 Binary files /dev/null and b/NERtcCallUIKit/NERtcCallUIKit/Assets/avchat_ring.mp3 differ diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/en.lproj/Localizable.strings b/NERtcCallUIKit/NERtcCallUIKit/Assets/en.lproj/Localizable.strings index 9ab47fd7..c684d74d 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Assets/en.lproj/Localizable.strings +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/en.lproj/Localizable.strings @@ -35,3 +35,9 @@ "waitting_remote_accept"="Waitting to connect"; "calling"="Calling"; "cancel_failed"="The invitation has been accepted and cannot be canceled"; + +"operation_failed"="operation failed"; + +"device_not_support"="The current device does not support virtualization"; + +"connecting"="Connecting…"; diff --git a/NERtcCallUIKit/NERtcCallUIKit/Assets/zh-Hans.lproj/Localizable.strings b/NERtcCallUIKit/NERtcCallUIKit/Assets/zh-Hans.lproj/Localizable.strings index bbac656f..a34ae8e3 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Assets/zh-Hans.lproj/Localizable.strings +++ b/NERtcCallUIKit/NERtcCallUIKit/Assets/zh-Hans.lproj/Localizable.strings @@ -11,7 +11,7 @@ "remote_cancel"="对方取消"; "remote_busy"="对方占线"; "remote_timeout"="对方超时未响应"; -"remote_reject"="对方已经拒绝"; +"remote_reject"="对方已拒绝"; "other_client_accept"="已被其他端接受"; "other_client_reject"="已被其他端拒绝"; @@ -34,3 +34,9 @@ "waitting_remote_accept"="等待对方接听……"; "calling"="正在呼叫"; "cancel_failed"="邀请已接受无法取消"; + +"operation_failed"="操作失败"; + +"device_not_support"="当前设备不支持虚化"; + +"connecting"="正在接通中…"; diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.h index 8fbc58c5..8245cf7d 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.h +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.h @@ -3,9 +3,9 @@ // found in the LICENSE file. #import -#import "NECallParam.h" +#import "NECallUIKitConfig.h" #import "NECustomButton.h" -#import "NERtcCallUIConfig.h" +#import "NEUICallParam.h" #import "NEVideoOperationView.h" #import "NEVideoView.h" @class NECallViewController; @@ -13,13 +13,21 @@ NS_ASSUME_NONNULL_BEGIN @interface NECallUIStateController : UIViewController +/// 视频窗口(小) @property(strong, nonatomic) NEVideoView *smallVideoView; +/// 视频窗口(大) @property(strong, nonatomic) NEVideoView *bigVideoView; +/// 远端用户头像(主叫状态) @property(strong, nonatomic) UIImageView *remoteAvatorView; +/// 远端用户头像(被叫&音频通话模式下使用) @property(strong, nonatomic) UIImageView *remoteBigAvatorView; +/// 主叫远端用户显示(正在呼叫xxxxx...) @property(strong, nonatomic) UILabel *titleLabel; +/// 远端用户名显示(被叫状态) @property(strong, nonatomic) UILabel *centerTitleLabel; +/// 远端操作状态标签(主叫状态) @property(strong, nonatomic) UILabel *subTitleLabel; +/// 邀请通话类型&远端状态 @property(strong, nonatomic) UILabel *centerSubtitleLabel; /// 取消呼叫 @@ -32,29 +40,26 @@ NS_ASSUME_NONNULL_BEGIN @property(strong, nonatomic) NECustomButton *microphoneBtn; /// 扬声器 @property(strong, nonatomic) NECustomButton *speakerBtn; - +/// 通话中音视频操作工具栏 @property(strong, nonatomic) NEVideoOperationView *operationView; -// YES 主叫 NO 被叫 -@property(nonatomic, assign) BOOL isCaller; - -@property(nonatomic, weak) NECallParam *callParam; - +/// 呼叫参数 +@property(nonatomic, weak) NEUICallParam *callParam; +/// 配置参数 @property(nonatomic, weak) NECallUIConfig *config; -@property(nonatomic, assign) CGFloat statusHeight; - -@property(assign, nonatomic) CGFloat radius; - -@property(assign, nonatomic) CGFloat titleFontSize; - -@property(assign, nonatomic) CGFloat subTitleFontSize; - -@property(assign, nonatomic) CGFloat factor; - -@property(assign, nonatomic) CGSize buttonSize; - -@property(nonatomic, assign) NERtcCallType callType; +/// 状态栏高度 +@property(nonatomic, assign, readonly) CGFloat statusHeight; +/// 内部圆角 +@property(nonatomic, assign, readonly) CGFloat radius; +/// 标题字号 +@property(nonatomic, assign, readonly) CGFloat titleFontSize; +/// 子标题字号 +@property(nonatomic, assign, readonly) CGFloat subTitleFontSize; +/// 小屏幕适配系数 +@property(nonatomic, assign, readonly) CGFloat factor; +/// 通话前按钮大小(挂断 接听 取消) +@property(nonatomic, assign, readonly) CGSize buttonSize; @property(nonatomic, weak) NECallViewController *mainController; @@ -78,6 +83,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)refreshVideoView; +- (NSString *)localizableWithKey:(NSString *)key; + @end NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.m index e7b18d40..78aed788 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallUIStateController.m @@ -12,6 +12,18 @@ @interface NECallUIStateController () @property(nonatomic, weak) UIView *parentView; +@property(nonatomic, assign, readwrite) CGFloat statusHeight; + +@property(nonatomic, assign, readwrite) CGFloat radius; + +@property(nonatomic, assign, readwrite) CGFloat titleFontSize; + +@property(nonatomic, assign, readwrite) CGFloat subTitleFontSize; + +@property(nonatomic, assign, readwrite) CGFloat factor; + +@property(nonatomic, assign, readwrite) CGSize buttonSize; + @end @implementation NECallUIStateController @@ -24,16 +36,11 @@ - (instancetype)init { self.titleFontSize = 20.0; self.subTitleFontSize = 14.0; self.buttonSize = CGSizeMake(75, 103); - self.bundle = [NSBundle bundleForClass:self.class]; + self.bundle = [NSBundle bundleForClass:NECallViewController.class]; } return self; } -//- (void)loadView { -// NSLog(@"state view load parent view %@",self.parentView); -// self.view = self.parentView; -//} - - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. @@ -82,8 +89,15 @@ - (NEVideoView *)smallVideoView { - (void)switchVideoView:(UITapGestureRecognizer *)tap { self.mainController.showMyBigView = !self.mainController.showMyBigView; [self refreshVideoView]; - // TODO: 代码整理 - // [self changeDefaultImage:self.operationView.cameraBtn.selected]; + [self.mainController changeDefaultImage:self.operationView.cameraBtn.selected]; + + if (self.mainController.showMyBigView) { + [self.mainController changeRemoteMute:self.mainController.isRemoteMute + videoView:self.smallVideoView]; + } else { + [self.mainController changeRemoteMute:self.mainController.isRemoteMute + videoView:self.bigVideoView]; + } } - (UIImageView *)remoteAvatorView { @@ -354,26 +368,28 @@ - (void)setupCalledUI { } - (NSString *)getInviteText { - return (self.callType == NERtcCallTypeAudio ? [self localizableWithKey:@"invite_audio_call"] - : [self localizableWithKey:@"invite_video_call"]); + return (self.callParam.callType == NERtcCallTypeAudio + ? [self localizableWithKey:@"invite_audio_call"] + : [self localizableWithKey:@"invite_video_call"]); } - (void)refreshVideoView { + NSLog(@"show my big view : %d", self.mainController.showMyBigView); + NSLog(@"self.operationView.cameraBtn.selected : %d", self.operationView.cameraBtn.selected); + if (self.mainController.showMyBigView) { - [[NERtcCallKit sharedInstance] setupLocalView:self.bigVideoView.videoView]; - [[NERtcCallKit sharedInstance] setupRemoteView:self.smallVideoView.videoView - forUser:self.callParam.remoteUserAccid]; + [[NECallEngine sharedInstance] setupLocalView:self.bigVideoView.videoView]; + [[NECallEngine sharedInstance] setupRemoteView:self.smallVideoView.videoView]; NSLog(@"show my big view"); - self.smallVideoView.maskView.hidden = self.mainController.remoteCameraAvailable; + self.smallVideoView.maskView.hidden = !self.mainController.isRemoteMute; self.bigVideoView.maskView.hidden = !self.operationView.cameraBtn.selected; self.bigVideoView.userID = self.callParam.currentUserAccid; self.smallVideoView.userID = self.callParam.remoteUserAccid; } else { - [[NERtcCallKit sharedInstance] setupLocalView:self.smallVideoView.videoView]; - [[NERtcCallKit sharedInstance] setupRemoteView:self.bigVideoView.videoView - forUser:self.callParam.remoteUserAccid]; + [[NECallEngine sharedInstance] setupLocalView:self.smallVideoView.videoView]; + [[NECallEngine sharedInstance] setupRemoteView:self.bigVideoView.videoView]; NSLog(@"show my small view"); - self.bigVideoView.maskView.hidden = self.mainController.remoteCameraAvailable; + self.bigVideoView.maskView.hidden = !self.mainController.isRemoteMute; self.smallVideoView.maskView.hidden = !self.operationView.cameraBtn.selected; self.bigVideoView.userID = self.callParam.remoteUserAccid; self.smallVideoView.userID = self.callParam.currentUserAccid; diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewBaseController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewBaseController.h new file mode 100644 index 00000000..f89b3450 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewBaseController.h @@ -0,0 +1,78 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import "NERingPlayerManager.h" +#import "NEUICallParam.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NECallViewBaseController : UIViewController + +@property(nonatomic, strong, nullable) NEUICallParam *callParam; + +@property(nonatomic, strong) UIPanGestureRecognizer *panGesture; + +@property(nonatomic, assign) CGFloat screenWidth; + +@property(nonatomic, assign) CGFloat screenHeight; + +/// 悬浮窗边距 +@property(nonatomic, assign) CGFloat floatMargin; + +/// 当前是否是小窗模式 +@property(nonatomic, assign) BOOL isSmallWindow; + +/// 音频浮窗 +@property(nonatomic, strong) UIView *audioSmallView; + +/// 音频小窗计时器 +@property(nonatomic, strong) UILabel *audioSmallViewTimerLabel; + +/// 资源包context +@property(nonatomic, strong) NSBundle *bundle; + +/// 小窗模式根视图view。也作为视频通话小窗模式下的远端的预览视图 +@property(nonatomic, strong) UIView *recoveryView; + +/// 远端关闭视频视图 +@property(nonatomic, strong) UIView *maskView; + +/// 视频小窗模式下,远端关闭摄像头状态下的头像 +@property(nonatomic, strong) UIImageView *remoteHeaderImage; + +// 远端视频是否是否关闭 +@property(nonatomic, assign) BOOL isRemoteMute; + +@property(nonatomic, assign) SEL createPipSEL; + +@property(nonatomic, assign) SEL stopPipSEL; + +/// 只用于跟未接通原因(话单)相关的toast,可根据外部配置是否显示toast +- (void)showToastWithContent:(NSString *)content; + +- (void)setupSmallWindown; + +- (void)changeToSmall; + +- (void)changeToNormal; + +/// 播放铃声 +- (void)playRingWithType:(CallRingType)ringType; + +/// 停止播放量铃声 +- (void)stopCurrentPlaying; + +// 设置声音设置输出到听筒 +- (void)setAudioOutputToReceiver; + +// 设置声音输出到扬声器 +- (void)setAudioOutputToSpeaker; + +// 获取非呼叫组件弹出的默认window +- (UIWindow *)preiousWindow; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewBaseController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewBaseController.m new file mode 100644 index 00000000..45dcf1f4 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewBaseController.m @@ -0,0 +1,364 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallViewBaseController.h" +#import +#import +#import +#import "NECallKitUtil.h" +#import "NERtcCallUIKit.h" + +@interface NECallViewBaseController () + +@property(nonatomic, assign) BOOL isPlaying; + +@property(nonatomic, assign) CallRingType ringType; + +@property(nonatomic, assign) BOOL isReceiver; + +@end + +@implementation NECallViewBaseController + +- (instancetype)init { + self = [super init]; + if (self) { + // 获取屏幕宽高 + UIScreen *screen = [UIScreen mainScreen]; + self.screenWidth = screen.bounds.size.width; + self.screenHeight = screen.bounds.size.height; + self.floatMargin = 10; + self.bundle = [NSBundle bundleForClass:NECallViewBaseController.class]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleInterruption:) + name:AVAudioSessionInterruptionNotification + object:nil]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] + removeObserver:self + name:AVAudioSessionSilenceSecondaryAudioHintNotification + object:nil]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + if (self.isPlaying && self.ringType == CRTCallerRing) { + [self stopCurrentPlaying]; + } +} + +- (void)setupSmallWindown { + [self.view addSubview:self.recoveryView]; + [NSLayoutConstraint activateConstraints:@[ + [self.recoveryView.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [self.recoveryView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor], + [self.recoveryView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor], + [self.recoveryView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] + ]]; + [self.view addGestureRecognizer:self.panGesture]; + self.view.clipsToBounds = YES; + + [self.view addSubview:self.maskView]; + [NSLayoutConstraint activateConstraints:@[ + [self.maskView.topAnchor constraintEqualToAnchor:self.recoveryView.topAnchor], + [self.maskView.leftAnchor constraintEqualToAnchor:self.recoveryView.leftAnchor], + [self.maskView.rightAnchor constraintEqualToAnchor:self.recoveryView.rightAnchor], + [self.maskView.bottomAnchor constraintEqualToAnchor:self.recoveryView.bottomAnchor] + ]]; + + [self.maskView addSubview:self.remoteHeaderImage]; + [NSLayoutConstraint activateConstraints:@[ + [self.remoteHeaderImage.centerXAnchor constraintEqualToAnchor:self.maskView.centerXAnchor], + [self.remoteHeaderImage.centerYAnchor constraintEqualToAnchor:self.maskView.centerYAnchor], + [self.remoteHeaderImage.widthAnchor constraintEqualToConstant:42], + [self.remoteHeaderImage.heightAnchor constraintEqualToConstant:42] + ]]; + + [self.recoveryView addSubview:self.audioSmallView]; + [NSLayoutConstraint activateConstraints:@[ + [self.audioSmallView.leftAnchor constraintEqualToAnchor:self.recoveryView.leftAnchor], + [self.audioSmallView.topAnchor constraintEqualToAnchor:self.recoveryView.topAnchor], + [self.audioSmallView.bottomAnchor constraintEqualToAnchor:self.recoveryView.bottomAnchor], + [self.audioSmallView.rightAnchor constraintEqualToAnchor:self.recoveryView.rightAnchor] + ]]; + + UIImage *callImage = [UIImage imageNamed:@"phone_image" + inBundle:self.bundle + compatibleWithTraitCollection:nil]; + + UIImageView *callImageView = [[UIImageView alloc] initWithImage:callImage]; + callImageView.translatesAutoresizingMaskIntoConstraints = NO; + [self.audioSmallView addSubview:callImageView]; + [NSLayoutConstraint activateConstraints:@[ + [callImageView.centerXAnchor constraintEqualToAnchor:self.audioSmallView.centerXAnchor], + [callImageView.topAnchor constraintEqualToAnchor:self.audioSmallView.topAnchor constant:11] + ]]; + + [self.audioSmallView addSubview:self.audioSmallViewTimerLabel]; + [NSLayoutConstraint activateConstraints:@[ + [self.audioSmallViewTimerLabel.centerXAnchor + constraintEqualToAnchor:self.audioSmallView.centerXAnchor], + [self.audioSmallViewTimerLabel.bottomAnchor + constraintEqualToAnchor:self.audioSmallView.bottomAnchor + constant:-15], + [self.audioSmallViewTimerLabel.leftAnchor constraintEqualToAnchor:self.audioSmallView.leftAnchor + constant:3], + [self.audioSmallViewTimerLabel.rightAnchor + constraintEqualToAnchor:self.audioSmallView.rightAnchor + constant:-3] + ]]; + + [self.remoteHeaderImage sd_setImageWithURL:[NSURL URLWithString:self.callParam.remoteAvatar] + placeholderImage:[UIImage imageNamed:@"avator" + inBundle:self.bundle + compatibleWithTraitCollection:nil]]; +} + +- (void)showToastWithContent:(NSString *)content { + if (self.callParam.enableShowRecorderToast == NO) { + return; + } + if (content.length <= 0) { + return; + } + + [self.preiousWindow ne_makeToast:content]; +} + +- (BOOL)isJoinRtcWhenCall { + BOOL enableJoinWhenCall = + [[[NECallEngine sharedInstance] valueForKeyPath:@"context.joinRtcWhenCall"] boolValue]; + + return enableJoinWhenCall; +} + +- (void)changeToSmall { + [[NERtcCallUIKit sharedInstance] changeSmallModeWithTyple:self.callParam.callType]; + self.recoveryView.hidden = NO; + self.panGesture.enabled = YES; + if (self.callParam.callType == NECallTypeVideo) { + [[NECallEngine sharedInstance] setupRemoteView:self.recoveryView]; + self.audioSmallView.hidden = YES; + self.view.layer.cornerRadius = 0; + if (self.isRemoteMute == YES) { + self.maskView.hidden = NO; + } + } else { + self.audioSmallView.hidden = NO; + self.view.layer.cornerRadius = 6; + } + self.isSmallWindow = YES; +} + +- (void)changeToNormal { + [[NERtcCallUIKit sharedInstance] restoreNormalMode]; + self.recoveryView.hidden = YES; + self.panGesture.enabled = NO; + self.isSmallWindow = NO; + self.view.layer.cornerRadius = 0; + self.maskView.hidden = YES; +} + +- (void)handlePan:(UIPanGestureRecognizer *)gesture { + if (gesture.state == UIGestureRecognizerStateChanged) { + CGPoint translation = [gesture translationInView:self.view]; + self.view.transform = + CGAffineTransformTranslate(self.view.transform, translation.x, translation.y); + [gesture setTranslation:CGPointZero inView:self.view]; + } else if (gesture.state == UIGestureRecognizerStateCancelled || + gesture.state == UIGestureRecognizerStateEnded || + gesture.state == UIGestureRecognizerStateFailed || + gesture.state == UIGestureRecognizerStateRecognized) { + CGPoint point = CGPointZero; + if (gesture.view.frame.origin.x + gesture.view.frame.size.width / 2.0 < + self.screenWidth / 2.0) { + point.x = self.floatMargin; + } else { + point.x = self.screenWidth - self.floatMargin - gesture.view.frame.size.width; + } + if (gesture.view.frame.origin.y - self.floatMargin <= 0) { + point.y = self.floatMargin; + } else if (gesture.view.frame.origin.y + gesture.view.frame.size.height + self.floatMargin > + self.screenHeight) { + point.y = self.screenHeight - gesture.view.frame.size.height - self.floatMargin; + } else { + point.y = gesture.view.frame.origin.y; + } + [UIView animateWithDuration:0.5 + animations:^{ + gesture.view.frame = + CGRectMake(point.x, point.y, gesture.view.frame.size.width, + gesture.view.frame.size.height); + }]; + } +} + +#pragma mark - call ring play + +- (void)playRingWithType:(CallRingType)ringType { + if ([self isJoinRtcWhenCall]) { + return; + } + self.isPlaying = YES; + self.ringType = ringType; + [[NERingPlayerManager shareInstance] playRingWithRingType:ringType isRtcPlay:NO]; +} + +- (void)stopCurrentPlaying { + if ([self isJoinRtcWhenCall]) { + return; + } + self.isPlaying = NO; + [[NERingPlayerManager shareInstance] stopCurrentPlaying]; +} + +// 设置声音设置输出到听筒 +- (void)setAudioOutputToReceiver { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session setCategory:AVAudioSessionCategoryPlayAndRecord + withOptions:AVAudioSessionCategoryOptionAllowBluetooth | + AVAudioSessionCategoryOptionAllowBluetoothA2DP + error:nil]; + [session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil]; + [session setActive:YES error:nil]; + self.isReceiver = YES; +} + +// 设置声音输出到扬声器 +- (void)setAudioOutputToSpeaker { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session setCategory:AVAudioSessionCategoryPlayback + withOptions:AVAudioSessionCategoryOptionAllowBluetooth | + AVAudioSessionCategoryOptionAllowBluetoothA2DP + + error:nil]; + [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil]; + [session setActive:YES error:nil]; + self.isReceiver = NO; +} + +- (void)handleInterruption:(NSNotification *)notification { + NSDictionary *userInfo = notification.userInfo; + if (userInfo == nil) { + return; + } + + AVAudioSessionInterruptionType type = + [[userInfo valueForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue]; + switch (type) { + case AVAudioSessionInterruptionTypeBegan: + // 中断开始,暂停播放 + + break; + case AVAudioSessionInterruptionTypeEnded: { + NERtcCallStatus status = NECallEngine.sharedInstance.callStatus; + if (self.isPlaying == YES && status != NECallStatusIdle) { + NSLog(@"handleInterruption playRingWithType happen"); + if (self.isReceiver == YES) { + [self setAudioOutputToReceiver]; + } else { + [self setAudioOutputToSpeaker]; + } + [self playRingWithType:self.ringType]; + } + } break; + default: + break; + } +} + +#pragma mark - lazy init + +- (UIView *)maskView { + if (_maskView == nil) { + // 实现一个渐变颜色的UIView + _maskView = [[UIView alloc] init]; + _maskView.translatesAutoresizingMaskIntoConstraints = NO; + CAGradientLayer *gradientLayer = [CAGradientLayer layer]; + gradientLayer.colors = @[ + (__bridge id)[NECallKitUtil colorWithHexString:@"#232529"].CGColor, + (__bridge id)[NECallKitUtil colorWithHexString:@"#5E6471"].CGColor + ]; + gradientLayer.locations = @[ @0.0, @1.0 ]; + gradientLayer.startPoint = CGPointMake(0, 0); + gradientLayer.endPoint = CGPointMake(0, 1); + gradientLayer.frame = CGRectMake(0, 0, 90, 160); + [_maskView.layer addSublayer:gradientLayer]; + _maskView.hidden = YES; + // 添加点击手势 + UITapGestureRecognizer *tap = + [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeToNormal)]; + [_maskView addGestureRecognizer:tap]; + } + return _maskView; +} + +- (UIImageView *)remoteHeaderImage { + if (_remoteHeaderImage == nil) { + _remoteHeaderImage = [[UIImageView alloc] init]; + _remoteHeaderImage.translatesAutoresizingMaskIntoConstraints = NO; + _remoteHeaderImage.contentMode = UIViewContentModeScaleAspectFit; + _remoteHeaderImage.clipsToBounds = YES; + _remoteHeaderImage.layer.cornerRadius = 4.0; + } + return _remoteHeaderImage; +} + +- (UIView *)recoveryView { + if (!_recoveryView) { + _recoveryView = [[UIView alloc] init]; + _recoveryView.translatesAutoresizingMaskIntoConstraints = NO; + _recoveryView.backgroundColor = [UIColor clearColor]; + _recoveryView.hidden = YES; + + UITapGestureRecognizer *tap = + [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeToNormal)]; + [_recoveryView addGestureRecognizer:tap]; + } + return _recoveryView; +} + +- (UIPanGestureRecognizer *)panGesture { + if (!_panGesture) { + _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; + _panGesture.enabled = NO; + } + return _panGesture; +} + +- (UIView *)audioSmallView { + if (_audioSmallView == nil) { + _audioSmallView = [[UIView alloc] init]; + _audioSmallView.translatesAutoresizingMaskIntoConstraints = NO; + _audioSmallView.backgroundColor = UIColor.whiteColor; + _audioSmallView.hidden = YES; + } + return _audioSmallView; +} + +- (UILabel *)audioSmallViewTimerLabel { + if (_audioSmallViewTimerLabel == nil) { + _audioSmallViewTimerLabel = [[UILabel alloc] init]; + _audioSmallViewTimerLabel.translatesAutoresizingMaskIntoConstraints = NO; + _audioSmallViewTimerLabel.textColor = [NECallKitUtil colorWithHexString:@"#1BBF52"]; + _audioSmallViewTimerLabel.adjustsFontSizeToFitWidth = YES; + _audioSmallViewTimerLabel.textAlignment = NSTextAlignmentCenter; + } + return _audioSmallViewTimerLabel; +} + +- (UIWindow *)preiousWindow { + return [[NERtcCallUIKit sharedInstance] valueForKey:@"preiousKeywindow"]; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.h index e8ecfa51..5de8dd31 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.h +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.h @@ -4,32 +4,35 @@ #import #import -#import "NECallParam.h" -#import "NERtcCallUIConfig.h" +#import "NECallUIKitConfig.h" +#import "NECallViewBaseController.h" +#import "NECustomButton.h" +#import "NEUICallParam.h" +#import "NEVideoView.h" NS_ASSUME_NONNULL_BEGIN extern NSString *const kCallKitDismissNoti; -@interface NECallViewController : UIViewController +@interface NECallViewController : NECallViewBaseController @property(nonatomic, assign) NERtcCallStatus status; -@property(nonatomic, assign) NERtcCallType callType; - -@property(nonatomic, strong) NECallParam *callParam; - @property(nonatomic, strong) NSMutableDictionary *uiConfigDic; @property(nonatomic, strong) NECallUIConfig *config; +/// 呼叫前音视频转换按钮 +@property(strong, nonatomic) NECustomButton *mediaSwitchBtn; + // 当前用户视频显示位置 @property(nonatomic, assign) BOOL showMyBigView; -@property(nonatomic, assign) BOOL remoteCameraAvailable; +- (void)changeDefaultImage:(BOOL)mute; + +- (void)changeRemoteMute:(BOOL)mute videoView:(NEVideoView *)remoteVideo; -// 主叫 -@property(nonatomic, assign) BOOL isCaller; +- (void)destroy; @end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.m index efa98ad7..ac4761b6 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECallViewController.m @@ -4,41 +4,38 @@ #import "NECallViewController.h" #import +#import +#import +#import #import -#import +#import +#include #import "NECallUIStateController.h" #import "NECustomButton.h" #import "NEExpandButton.h" #import "NERtcCallUIKit.h" #import "NEVideoOperationView.h" -#import "NEVideoView.h" #import "NetManager.h" -#import "SettingManager.h" NSString *const kCallKitDismissNoti = @"kCallKitDismissNoti"; NSString *const kCallKitShowNoti = @"kCallKitShowNoti"; -@interface NECallViewController () +@interface NECallViewController () @property(nonatomic, strong) UIButton *switchCameraBtn; -@property(strong, nonatomic) NEVideoOperationView *operationView; +@property(nonatomic, strong) NEVideoOperationView *operationView; -/// 音视频转换 -@property(strong, nonatomic) NECustomButton *mediaSwitchBtn; +@property(nonatomic, strong) UILabel *timerLabel; -@property(strong, nonatomic) UILabel *timerLabel; +@property(nonatomic, strong) NSTimer *timer; -@property(strong, nonatomic) NSTimer *timer; +@property(nonatomic, strong) UIImageView *blurImage; -@property(strong, nonatomic) UIImageView *blurImage; +@property(nonatomic, strong) UIToolbar *toolBar; -@property(strong, nonatomic) UIToolbar *toolBar; - -@property(assign, nonatomic) int timerCount; - -@property(nonatomic, assign) BOOL isPstn; // 当前呼叫是否已进入pstn流程,默认 NO +@property(nonatomic, assign) int timerCount; @property(nonatomic, strong) UIView *bannerView; @@ -46,9 +43,9 @@ @interface NECallViewController () @property(nonatomic, strong) UILabel *cnameLabel; -@property(nonatomic, assign) BOOL isRemoteMute; +@property(nonatomic, assign) CGFloat factor; -@property(assign, nonatomic) CGFloat factor; +@property(nonatomic, strong) UIButton *smallButton; /// 通话状态视图 @property(nonatomic, strong) NEAudioCallingController *audioCallingController; @@ -63,7 +60,7 @@ @interface NECallViewController () @property(nonatomic, weak) NECallUIStateController *stateUIController; -@property(nonatomic, strong) NSBundle *bundle; +@property(nonatomic, assign) BOOL isClickVirtual; @end @@ -74,7 +71,6 @@ - (instancetype)init { if (self) { self.timerCount = 0; self.factor = 1.0; - self.bundle = [NSBundle bundleForClass:self.class]; } return self; } @@ -83,17 +79,32 @@ - (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] postNotificationName:kCallKitShowNoti object:nil]; [[NERtcEngine sharedEngine] setParameters:@{kNERtcKeyVideoStartWithBackCamera : @NO}]; - if (self.callType == NERtcCallTypeVideo) { - self.remoteCameraAvailable = YES; + [self setupCommon]; + [self setupSmallWindown]; + [[NECallEngine sharedInstance] setValue:self forKey:@"engineDelegateEx"]; + [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; +} + +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + [[NECallEngine sharedInstance] setupLocalView:nil]; + if (self.callParam.enableVirtualBackground == YES && self.isClickVirtual == YES) { + [[NERtcEngine sharedEngine] enableVirtualBackground:NO backData:nil]; } + [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; +} + +#pragma mark - SDK + +- (void)setupCommon { [self setupUI]; - // [self setupCenterRemoteAvator]; [self setupSDK]; [self updateUIonStatus:self.status]; - if (self.isCaller == NO && [NERtcCallKit sharedInstance].callStatus == NERtcCallStatusIdle) { + if (self.callParam.isCaller == NO && + [NECallEngine sharedInstance].callStatus == NERtcCallStatusIdle) { __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ - [weakSelf onCallEnd]; + [weakSelf destroy]; }); } @@ -106,60 +117,58 @@ - (void)viewDidLoad { ]]; } -- (void)viewDidDisappear:(BOOL)animated { - [super viewDidDisappear:animated]; - [[NERtcCallKit sharedInstance] setupLocalView:nil]; -} - -#pragma mark - SDK - (void)setupSDK { - [[NERtcCallKit sharedInstance] addDelegate:self]; - [[NERtcCallKit sharedInstance] enableLocalVideo:YES]; + [[NECallEngine sharedInstance] addCallDelegate:self]; + [[NECallEngine sharedInstance] enableLocalVideo:YES]; __weak typeof(self) weakSelf = self; if (self.status == NERtcCallStatusCalling) { - [[NERtcCallKit sharedInstance] - call:self.callParam.remoteUserAccid - type:self.callType ? self.callType : NERtcCallTypeVideo - attachment:self.callParam.attachment - globalExtra:self.callParam.extra - withToken:self.callParam.token - channelName:self.callParam.channelName - completion:^(NSError *_Nullable error) { - NSLog(@"call error code : %@", error); - __strong typeof(self) strongSelf = weakSelf; - if (strongSelf.callType == NERtcCallTypeVideo) { - if ([[SettingManager shareInstance] isGlobalInit] == YES) { - __weak typeof(self) weakSelf2 = strongSelf; - dispatch_async(dispatch_get_main_queue(), ^{ - __strong typeof(self) strongSelf2 = weakSelf2; - [[NERtcCallKit sharedInstance] - setupLocalView:strongSelf2.videoCallingController.bigVideoView.videoView]; - }); - } - strongSelf.videoCallingController.bigVideoView.userID = - strongSelf.callParam.currentUserAccid; - } - - if (error) { - /// 对方离线时 通过APNS推送 UI不弹框提示 - if (error.code == 10202 || error.code == 10201) { - return; - } else { - [strongSelf onCallEnd]; - } - [UIApplication.sharedApplication.keyWindow makeToast:error.localizedDescription]; - } - }]; - } -} + [self playRingWithType:CRTCallerRing]; + if (self.callParam.callType == NECallTypeAudio && self.callParam.isCaller == YES) { + [self setAudioOutputToReceiver]; + } -- (void)setCallType:(NERtcCallType)callType { - NSLog(@"set current call type : %lu", (unsigned long)callType); - _callType = callType; + NECallParam *param = [[NECallParam alloc] initWithAccId:self.callParam.remoteUserAccid + withCallType:self.callParam.callType]; + param.globalExtraCopy = self.callParam.extra; + param.rtcChannelName = self.callParam.channelName; + param.extraInfo = self.callParam.attachment; + param.pushConfig = self.callParam.pushConfig; + + [[NECallEngine sharedInstance] + call:param + completion:^(NSError *_Nullable error, NECallInfo *_Nullable callInfo) { + YXAlogInfo(@"callkit call callback ne call info : %@", [callInfo yx_modelToJSONString]); + if (weakSelf.callParam.callType == NERtcCallTypeVideo) { + if ([self isGlobalInit] == YES) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[NECallEngine sharedInstance] + setupLocalView:weakSelf.videoCallingController.bigVideoView.videoView]; + }); + } + weakSelf.videoCallingController.bigVideoView.userID = + weakSelf.callParam.currentUserAccid; + } + + if (error) { + /// 对方离线时 通过APNS推送 UI不弹框提示 + YXAlogInfo(@"call view controller call error : %@", error.localizedDescription); + if (error.code == NIMRemoteErrorCodeSignalResPeerPushOffline || + error.code == NIMRemoteErrorCodeSignalResPeerNIMOffline) { + return; + } else { + [weakSelf destroy]; + } + [weakSelf.preiousWindow ne_makeToast:error.localizedDescription]; + } + }]; + } else { + [self playRingWithType:CRTCalleeRing]; + } } #pragma mark - UI + - (void)setupUI { if (self.view.frame.size.height < 600) { self.factor = 0.5; @@ -197,14 +206,36 @@ - (void)setupUI { [self setupChildController]; - [self.view addSubview:self.switchCameraBtn]; - [NSLayoutConstraint activateConstraints:@[ - [self.switchCameraBtn.topAnchor constraintEqualToAnchor:self.view.topAnchor - constant:statusHeight + 20], - [self.switchCameraBtn.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:20], - [self.switchCameraBtn.heightAnchor constraintEqualToConstant:30], - [self.switchCameraBtn.widthAnchor constraintEqualToConstant:30] - ]]; + if (self.callParam.enableFloatingWindow == YES) { + [self.view addSubview:self.smallButton]; + [NSLayoutConstraint activateConstraints:@[ + [self.smallButton.topAnchor constraintEqualToAnchor:self.view.topAnchor + constant:statusHeight + 20], + [self.smallButton.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:20], + [self.smallButton.widthAnchor constraintEqualToConstant:40], + [self.smallButton.heightAnchor constraintEqualToConstant:40] + ]]; + + [self.view addSubview:self.switchCameraBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.switchCameraBtn.topAnchor constraintEqualToAnchor:self.smallButton.topAnchor + constant:0], + [self.switchCameraBtn.leftAnchor constraintEqualToAnchor:self.smallButton.rightAnchor + constant:10], + [self.switchCameraBtn.heightAnchor constraintEqualToConstant:40], + [self.switchCameraBtn.widthAnchor constraintEqualToConstant:40] + ]]; + + } else { + [self.view addSubview:self.switchCameraBtn]; + [NSLayoutConstraint activateConstraints:@[ + [self.switchCameraBtn.topAnchor constraintEqualToAnchor:self.view.topAnchor + constant:statusHeight + 20], + [self.switchCameraBtn.leftAnchor constraintEqualToAnchor:self.view.leftAnchor constant:20], + [self.switchCameraBtn.heightAnchor constraintEqualToConstant:40], + [self.switchCameraBtn.widthAnchor constraintEqualToConstant:40] + ]]; + } [self.view addSubview:self.operationView]; [NSLayoutConstraint activateConstraints:@[ @@ -227,6 +258,7 @@ - (void)setupUI { [self.mediaSwitchBtn.heightAnchor constraintEqualToConstant:buttonSize.height], [self.mediaSwitchBtn.widthAnchor constraintEqualToConstant:buttonSize.width] ]]; + self.mediaSwitchBtn.hidden = YES; [self.mediaSwitchBtn.maskBtn addTarget:self @@ -244,14 +276,18 @@ - (void)setupUI { - (void)setCallingTypeSwith:(BOOL)show { if (show == YES && self.config.showCallingSwitchCallType == YES) { - self.mediaSwitchBtn.hidden = NO; + if ([self isSupportAutoJoinWhenCalled] == YES) { + self.mediaSwitchBtn.hidden = NO; + } else { + self.mediaSwitchBtn.hidden = YES; + } } else { self.mediaSwitchBtn.hidden = YES; } } - (void)setupChildController { - if (self.isCaller == YES) { + if (self.callParam.isCaller == YES) { [self addChildViewController:self.videoCallingController]; [self.view addSubview:self.videoCallingController.view]; [self addChildViewController:self.audioCallingController]; @@ -295,10 +331,11 @@ - (void)updateUIonStatus:(NERtcCallStatus)status { [self setCallingTypeSwith:YES]; self.operationView.hidden = YES; self.stateUIController.view.hidden = YES; - if (self.callType == NERtcCallTypeVideo) { + if (self.callParam.callType == NECallTypeVideo) { self.stateUIController = self.videoCallingController; [self.videoCallingController refreshUI]; [self setSwitchAudioStyle]; + } else { self.stateUIController = self.audioCallingController; [self setSwitchVideoStyle]; @@ -313,7 +350,7 @@ - (void)updateUIonStatus:(NERtcCallStatus)status { self.stateUIController = self.calledController; self.stateUIController.view.hidden = NO; [self.calledController refreshUI]; - if (self.callType == NERtcCallTypeVideo) { + if (self.callParam.callType == NECallTypeVideo) { self.mediaSwitchBtn.imageView.image = [UIImage imageNamed:@"switch_audio" inBundle:self.bundle compatibleWithTraitCollection:nil]; @@ -327,21 +364,21 @@ - (void)updateUIonStatus:(NERtcCallStatus)status { [self setSwitchVideoStyle]; } __weak typeof(self) weakSelf = self; + [self.calledController checkCallePreview]; [self.calledController.remoteBigAvatorView sd_setImageWithURL:[NSURL URLWithString:self.callParam.remoteAvatar] completed:^(UIImage *_Nullable image, NSError *_Nullable error, SDImageCacheType cacheType, NSURL *_Nullable imageURL) { - __strong typeof(self) strongSelf = weakSelf; if (image == nil) { image = [UIImage imageNamed:@"avator" - inBundle:strongSelf.bundle + inBundle:weakSelf.bundle compatibleWithTraitCollection:nil]; } - if (strongSelf.isCaller == false && - strongSelf.callType == NERtcCallTypeVideo) { - [strongSelf.blurImage setHidden:NO]; + if (weakSelf.callParam.isCaller == false && + weakSelf.callParam.callType == NECallTypeVideo) { + [weakSelf.blurImage setHidden:NO]; } - strongSelf.blurImage.image = image; + weakSelf.blurImage.image = image; }]; } break; @@ -349,13 +386,25 @@ - (void)updateUIonStatus:(NERtcCallStatus)status { [self setCallingTypeSwith:NO]; self.operationView.hidden = NO; self.stateUIController.view.hidden = YES; - if (self.callType == NERtcCallTypeVideo) { + self.smallButton.hidden = NO; + if (self.callParam.callType == NECallTypeVideo) { self.stateUIController = self.videoInCallController; self.switchCameraBtn.hidden = NO; + self.isRemoteMute = NO; + self.videoInCallController.operationView.cameraBtn.selected = NO; + self.videoInCallController.smallVideoView.imageView.hidden = YES; + self.videoInCallController.bigVideoView.imageView.hidden = YES; [self.videoInCallController refreshUI]; + if (self.callParam.enableVideoToAudio == NO) { + [self.operationView removeMediaBtn]; + } } else { [self.operationView changeAudioStyle]; self.stateUIController = self.audioInCallController; + self.switchCameraBtn.hidden = YES; + if (self.callParam.enableAudioToVideo == NO) { + [self.operationView removeMediaBtn]; + } } self.stateUIController.view.hidden = NO; @@ -368,66 +417,56 @@ - (void)updateUIonStatus:(NERtcCallStatus)status { - (void)showVideoView { if (self.status == NERtcCallStatusCalling) { - [[NERtcCallKit sharedInstance] + [[NECallEngine sharedInstance] setupLocalView:self.videoCallingController.bigVideoView.videoView]; } if (self.status == NERtcCallStatusInCall) { - [[NERtcCallKit sharedInstance] + [[NECallEngine sharedInstance] setupLocalView:self.videoInCallController.smallVideoView.videoView]; - [[NERtcCallKit sharedInstance] setupRemoteView:self.videoInCallController.bigVideoView.videoView - forUser:self.callParam.remoteUserAccid]; + [[NECallEngine sharedInstance] + setupRemoteView:self.videoInCallController.bigVideoView.videoView]; } - [[NERtcCallKit sharedInstance] muteLocalAudio:NO]; - [[NERtcCallKit sharedInstance] muteLocalVideo:NO]; + [[NECallEngine sharedInstance] muteLocalVideo:NO]; + [[NECallEngine sharedInstance] muteLocalAudio:NO]; self.operationView.microPhone.selected = NO; self.operationView.cameraBtn.selected = NO; self.operationView.speakerBtn.selected = NO; self.operationView.microPhone.selected = NO; - NSError *error; - [[NERtcCallKit sharedInstance] setLoudSpeakerMode:YES error:&error]; + [[NERtcEngine sharedEngine] setLoudspeakerMode:YES]; [[NERtcEngine sharedEngine] muteLocalAudio:NO]; } - (void)hideVideoView { - [[NERtcCallKit sharedInstance] setupLocalView:nil]; - [[NERtcCallKit sharedInstance] setupRemoteView:nil forUser:nil]; + [[NECallEngine sharedInstance] setupLocalView:nil]; + [[NECallEngine sharedInstance] setupRemoteView:nil]; self.operationView.speakerBtn.selected = YES; self.operationView.microPhone.selected = NO; - NSError *error; - [[NERtcCallKit sharedInstance] setLoudSpeakerMode:NO error:&error]; + [[NERtcEngine sharedEngine] setLoudspeakerMode:NO]; [[NERtcEngine sharedEngine] muteLocalAudio:NO]; + if (self.callParam.enableVirtualBackground == YES && self.isClickVirtual == YES) { + [[NERtcEngine sharedEngine] enableVirtualBackground:NO backData:nil]; + } } #pragma mark - event -- (void)closeEvent:(UIButton *)button { - [[NERtcCallKit sharedInstance] hangup:^(NSError *_Nullable error){ - - }]; -} - - (void)cancelEvent:(UIButton *)button { __weak typeof(self) weakSelf = self; NSLog(@"cancel rtc"); if ([[NetManager shareInstance] isClose] == YES) { [self destroy]; } - [[NERtcCallKit sharedInstance] cancel:^(NSError *_Nullable error) { - NSLog(@"cancel error %@", error); - button.enabled = YES; - __strong typeof(weakSelf) strongSelf = weakSelf; - if (error.code == 20016) { - if ([UIApplication.sharedApplication respondsToSelector:@selector(keyWindow)]) { - [UIApplication.sharedApplication.keyWindow - makeToast:[strongSelf localizableWithKey:@"cancel_failed"]]; - } - } else { - [strongSelf destroy]; - } - }]; + NEHangupParam *param = [[NEHangupParam alloc] init]; + [[NECallEngine sharedInstance] hangup:param + completion:^(NSError *_Nullable error) { + NSLog(@"cancel error %@", error); + button.enabled = YES; + [weakSelf destroy]; + }]; } + - (void)rejectEvent:(UIButton *)button { if ([[NetManager shareInstance] isClose] == YES) { [self destroy]; @@ -435,25 +474,16 @@ - (void)rejectEvent:(UIButton *)button { self.calledController.acceptBtn.userInteractionEnabled = NO; __weak typeof(self) weakSelf = self; - if ([[SettingManager shareInstance] rejectBusyCode] == YES) { - [[NERtcCallKit sharedInstance] - rejectWithReason:TerminalCodeBusy - withCompletion:^(NSError *_Nullable error) { - __strong typeof(self) strongSelf = weakSelf; - strongSelf.calledController.acceptBtn.userInteractionEnabled = YES; - [strongSelf destroy]; - }]; - } else { - [[NERtcCallKit sharedInstance] reject:^(NSError *_Nullable error) { - __strong typeof(self) strongSelf = weakSelf; - strongSelf.calledController.acceptBtn.userInteractionEnabled = YES; - [strongSelf destroy]; - }]; - } + NEHangupParam *param = [[NEHangupParam alloc] init]; + [[NECallEngine sharedInstance] hangup:param + completion:^(NSError *_Nullable error) { + weakSelf.calledController.acceptBtn.userInteractionEnabled = YES; + }]; } + - (void)acceptEvent:(UIButton *)button { if ([[NetManager shareInstance] isClose] == YES) { - [self.view makeToast:[self localizableWithKey:@"network_error"]]; + [self.view ne_makeToast:[self localizableWithKey:@"network_error"]]; return; } @@ -461,38 +491,30 @@ - (void)acceptEvent:(UIButton *)button { self.calledController.acceptBtn.userInteractionEnabled = NO; __weak typeof(self) weakSelf = self; - [[NERtcCallKit sharedInstance] - acceptWithToken:[[SettingManager shareInstance] customToken] - withCompletion:^(NSError *_Nullable error) { - __strong typeof(self) strongSelf = weakSelf; - strongSelf.calledController.rejectBtn.userInteractionEnabled = YES; - strongSelf.calledController.acceptBtn.userInteractionEnabled = YES; - if (error) { - if (error.code != 10420) { - [UIApplication.sharedApplication.keyWindow - makeToast:[NSString - stringWithFormat:@"%@ %@", - [strongSelf localizableWithKey:@"accept_failed"], - error.localizedDescription]]; - } - __weak typeof(self) weakSelf2 = strongSelf; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), - dispatch_get_main_queue(), ^{ - __strong typeof(self) strongSelf2 = weakSelf2; - [strongSelf2 destroy]; - }); - } else { - [[NERtcCallKit sharedInstance] memberOfAccid:@"" - completion:^(NIMSignalingMemberInfo *_Nullable info){ - - }]; - [strongSelf updateUIonStatus:NERtcCallStatusInCall]; - [strongSelf startTimer]; - } - }]; + [[NECallEngine sharedInstance] accept:^(NSError *_Nullable error, + NECallInfo *_Nullable callInfo) { + weakSelf.calledController.rejectBtn.userInteractionEnabled = YES; + weakSelf.calledController.acceptBtn.userInteractionEnabled = YES; + if (error) { + if (error.code != 10420) { + [weakSelf.preiousWindow + ne_makeToast:[NSString stringWithFormat:@"%@ %@", + [weakSelf localizableWithKey:@"accept_failed"], + error.localizedDescription]]; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [weakSelf destroy]; + }); + } else { + self.calledController.connectingLabel.hidden = NO; + [self stopCurrentPlaying]; + } + }]; } + - (void)switchCameraBtn:(UIButton *)button { - [[NERtcCallKit sharedInstance] switchCamera]; + [[NECallEngine sharedInstance] switchCamera]; button.selected = !button.selected; if (button.isSelected == YES) { [[NERtcEngine sharedEngine] setParameters:@{kNERtcKeyVideoStartWithBackCamera : @YES}]; @@ -500,360 +522,400 @@ - (void)switchCameraBtn:(UIButton *)button { [[NERtcEngine sharedEngine] setParameters:@{kNERtcKeyVideoStartWithBackCamera : @NO}]; } } + - (void)microPhoneClick:(UIButton *)button { button.selected = !button.selected; - [[NERtcCallKit sharedInstance] muteLocalAudio:button.selected]; + [[NECallEngine sharedInstance] muteLocalAudio:button.selected]; } + - (void)cameraBtnClick:(UIButton *)button { button.selected = !button.selected; NSLog(@"mute video select : %d", button.selected); - if ([[SettingManager shareInstance] useEnableLocalMute] == YES) { + if (self.callParam.useEnableLocalMute == YES) { NSLog(@"enableLocalVideo: %d", !button.selected); - [[NERtcCallKit sharedInstance] enableLocalVideo:!button.selected]; + [[NECallEngine sharedInstance] enableLocalVideo:!button.selected]; } else { - [[NERtcCallKit sharedInstance] muteLocalVideo:button.selected]; + [[NECallEngine sharedInstance] muteLocalVideo:button.selected]; } [self changeDefaultImage:button.selected]; [self cameraAvailble:!button.selected userId:self.callParam.currentUserAccid]; } -- (void)hangupBtnClick:(UIButton *)button { - [[NERtcCallKit sharedInstance] hangup:^(NSError *_Nullable error){ - - }]; - [self destroy]; +- (void)hangupBtnClick:(UIButton *)button { + if ([[NetManager shareInstance] isClose] == YES) { + [self destroy]; + } + NEHangupParam *param = [[NEHangupParam alloc] init]; + [[NECallEngine sharedInstance] hangup:param + completion:^(NSError *_Nullable error){ + }]; } + - (void)microphoneBtnClick:(UIButton *)button { NSLog(@"micro phone btn click : %d", button.imageView.highlighted); self.audioCallingController.microphoneBtn.imageView.highlighted = !self.audioCallingController.microphoneBtn.imageView.highlighted; - [[NERtcCallKit sharedInstance] + [[NECallEngine sharedInstance] muteLocalAudio:self.audioCallingController.microphoneBtn.imageView.highlighted]; _operationView.microPhone.selected = self.audioCallingController.microphoneBtn.imageView.highlighted; } + - (void)speakerBtnClick:(UIButton *)button { NSLog(@"speaker btn click : %d", self.audioCallingController.speakerBtn.imageView.highlighted); - NSError *error = nil; - - [[NERtcCallKit sharedInstance] - setLoudSpeakerMode:!self.audioCallingController.speakerBtn.imageView.highlighted - error:&error]; - if (error == nil) { + int ret = [[NERtcEngine sharedEngine] + setLoudspeakerMode:!self.audioCallingController.speakerBtn.imageView.highlighted]; + if (ret == 0) { self.audioCallingController.speakerBtn.imageView.highlighted = !self.audioCallingController.speakerBtn.imageView.highlighted; _operationView.speakerBtn.selected = !self.audioCallingController.speakerBtn.imageView.highlighted; + if (_operationView.speakerBtn.isSelected == YES) { + [self setAudioOutputToReceiver]; + } else { + [self setAudioOutputToSpeaker]; + } } else { - [self.view makeToast:error.description]; + [self.view ne_makeToast:[self localizableWithKey:@"operation_failed"]]; + } +} + +- (void)virtualBackgroundBtnClick:(UIButton *)button { + NSLog(@"virtualBackgroundBtnClick"); + button.selected = !button.selected; + self.isClickVirtual = YES; + + if (button.selected) { + NERtcVirtualBackgroundSource *source = [[NERtcVirtualBackgroundSource alloc] init]; + source.backgroundSourceType = kNERtcVirtualBackgroundBlur; + source.blur_degree = kNERtcBlurHigh; + [[NERtcEngine sharedEngine] enableVirtualBackground:YES backData:source]; + } else { + [[NERtcEngine sharedEngine] enableVirtualBackground:NO backData:nil]; } } - (void)operationSwitchClick:(UIButton *)btn { if ([[NetManager shareInstance] isClose] == YES) { - [self.view makeToast:[self localizableWithKey:@"network_error"]]; + [self.view ne_makeToast:[self localizableWithKey:@"network_error"]]; return; } __weak typeof(self) weakSelf = self; btn.enabled = NO; - NERtcCallType type = - self.callType == NERtcCallTypeVideo ? NERtcCallTypeAudio : NERtcCallTypeVideo; - [[NERtcCallKit sharedInstance] - switchCallType:type - withState:NERtcSwitchStateInvite + NECallType type = self.callParam.callType == NECallTypeVideo ? NECallTypeAudio : NECallTypeVideo; + + NESwitchParam *param = [[NESwitchParam alloc] init]; + param.state = NECallSwitchStateInvite; + param.callType = type; + + [[NECallEngine sharedInstance] + switchCallType:param completion:^(NSError *_Nullable error) { - __strong typeof(self) strongSelf = weakSelf; - // weakSelf.mediaSwitchBtn.enabled = YES; btn.enabled = YES; if (error == nil) { NSLog(@"切换成功 : %lu", type); NSLog(@"switch : %d", btn.selected); - if (type == NERtcCallTypeVideo && [SettingManager.shareInstance isVideoConfirm]) { - [strongSelf showBannerView]; - } else if (type == NERtcCallTypeAudio && - [SettingManager.shareInstance isAudioConfirm]) { - [strongSelf showBannerView]; + if (type == NECallTypeVideo && + [[NECallEngine sharedInstance] getCallConfig].enableSwitchVideoConfirm) { + [weakSelf showBannerView]; + } else if (type == NECallTypeAudio && + [[NECallEngine sharedInstance] getCallConfig].enableSwitchAudioConfirm) { + [weakSelf showBannerView]; } } else { - [strongSelf.view - makeToast:[NSString - stringWithFormat:@"%@: %@", - [strongSelf localizableWithKey:@"switch_error"], - error]]; + [weakSelf.view + ne_makeToast:[NSString + stringWithFormat:@"%@: %@", + [weakSelf localizableWithKey:@"switch_error"], + error]]; } }]; } - (void)operationSpeakerClick:(UIButton *)btn { - NSError *error = nil; - BOOL use; - [[NERtcEngine sharedEngine] getLoudspeakerMode:&use]; - NSLog(@"get loud speaker %d", use); - [[NERtcCallKit sharedInstance] setLoudSpeakerMode:btn.selected error:&error]; - if (error == nil) { + int ret = [NERtcEngine.sharedEngine setLoudspeakerMode:btn.selected]; + if (ret == 0) { btn.selected = !btn.selected; } else { - [self.view makeToast:error.description]; + [self.view ne_makeToast:[self localizableWithKey:@"operation_failed"]]; } } - (void)mediaClick:(UIButton *)btn { if ([[NetManager shareInstance] isClose] == YES) { - [self.view makeToast:[self localizableWithKey:@"network_error"]]; + [self.view ne_makeToast:[self localizableWithKey:@"network_error"]]; return; } __weak typeof(self) weakSelf = self; self.mediaSwitchBtn.maskBtn.enabled = NO; - NERtcCallType type = - weakSelf.callType == NERtcCallTypeVideo ? NERtcCallTypeAudio : NERtcCallTypeVideo; - [[NERtcCallKit sharedInstance] - switchCallType:type - withState:NERtcSwitchStateInvite + + NECallType type = + weakSelf.callParam.callType == NECallTypeVideo ? NECallTypeAudio : NECallTypeVideo; + + NESwitchParam *param = [[NESwitchParam alloc] init]; + param.state = NECallSwitchStateInvite; + param.callType = type; + + [[NECallEngine sharedInstance] + switchCallType:param completion:^(NSError *_Nullable error) { - __strong typeof(self) strongSelf = weakSelf; - strongSelf.mediaSwitchBtn.maskBtn.enabled = YES; + weakSelf.mediaSwitchBtn.maskBtn.enabled = YES; if (error == nil) { - if (type == NERtcCallTypeVideo && [SettingManager.shareInstance isVideoConfirm]) { - [strongSelf showBannerView]; - } else if (type == NERtcCallTypeAudio && - [SettingManager.shareInstance isAudioConfirm]) { - [strongSelf showBannerView]; + if (type == NECallTypeVideo && + [[NECallEngine sharedInstance] getCallConfig].enableSwitchVideoConfirm) { + [weakSelf showBannerView]; + } else if (type == NECallTypeAudio && + [[NECallEngine sharedInstance] getCallConfig].enableSwitchAudioConfirm) { + [weakSelf showBannerView]; } } else { - [strongSelf.view - makeToast:[NSString - stringWithFormat:@"%@ : %@", - [strongSelf localizableWithKey:@"switch_error"], - error]]; + [weakSelf.view + ne_makeToast:[NSString + stringWithFormat:@"%@ : %@", + [weakSelf localizableWithKey:@"switch_error"], + error]]; } }]; } -#pragma mark - NERtcVideoCallDelegate - -- (void)onDisconnect:(NSError *)reason { - [self destroy]; -} -- (void)onUserEnter:(NSString *)userID { - [self updateUIonStatus:NERtcCallStatusInCall]; - [self startTimer]; - if ([[SettingManager shareInstance] incallShowCName] == YES && - [self.cnameLabel superview] == nil) { - [self.view addSubview:self.cnameLabel]; - self.cnameLabel.text = - [NSString stringWithFormat:@"cname: %@", [[SettingManager shareInstance] getRtcCName]]; - [NSLayoutConstraint activateConstraints:@[ - [self.cnameLabel.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], - [self.cnameLabel.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor] - ]]; +- (void)onCallTypeChangeWithType:(NECallType)callType { + NSLog(@"onCallTypeChange:"); + if (self.callParam.callType == callType) { + return; } -} -- (void)onUserCancel:(NSString *)userID { - [[NERtcCallKit sharedInstance] hangup:^(NSError *_Nullable error){ - }]; - [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"remote_cancel"]]; - [self destroy]; -} -- (void)onCameraAvailable:(BOOL)available userID:(NSString *)userID { - self.isRemoteMute = !available; - [self cameraAvailble:available userId:userID]; -} -- (void)onVideoMuted:(BOOL)muted userID:(NSString *)userID { - self.isRemoteMute = muted; - [self cameraAvailble:!muted userId:userID]; -} -- (void)onUserLeave:(NSString *)userID { - NSLog(@"onUserLeave"); - [self destroy]; -} -- (void)onUserDisconnect:(NSString *)userID { - NSLog(@"onUserDiconnect"); - [self destroy]; -} -- (void)onCallingTimeOut { - if ([[NetManager shareInstance] isClose] == YES) { - [self destroy]; + self.callParam.callType = callType; + if (self.isSmallWindow == YES) { + [[NERtcCallUIKit sharedInstance] changeSmallModeWithTyple:self.callParam.callType]; + } + [self updateUIonStatus:self.status]; + + if (self.status == NERtcCallStatusInCall) { + switch (callType) { + case NECallTypeAudio: + NSLog(@"NERtcCallTypeAudio"); + [self.operationView changeAudioStyle]; + [self hideVideoView]; + break; + case NECallTypeVideo: + NSLog(@"NERtcCallTypeVideo"); + [self.operationView changeVideoStyle]; + [self showVideoView]; + break; + default: + break; + } return; } - [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"remote_timeout"]]; - [self destroy]; -} -- (void)onUserBusy:(NSString *)userID { - [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"remote_busy"]]; - [self destroy]; + + switch (callType) { + case NECallTypeAudio: + if (self.callParam.isCaller == YES && self.status == NERtcCallStatusCalling) { + [self setAudioOutputToReceiver]; + } + [self.operationView changeAudioStyle]; + [self setSwitchVideoStyle]; + break; + case NECallTypeVideo: + [self.operationView changeVideoStyle]; + [self setSwitchAudioStyle]; + break; + default: + break; + } } -- (void)onCallEnd { - [self destroy]; + +#pragma mark - call engine delegate + +- (void)onVideoMuted:(BOOL)muted userID:(NSString *)userId { + self.isRemoteMute = muted; + [self cameraAvailble:!muted userId:userId]; } -- (void)onUserReject:(NSString *)userID { - [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"remote_reject"]]; - [self destroy]; + +- (void)onVideoAvailable:(BOOL)available userID:(NSString *)userId { + self.isRemoteMute = !available; + [self cameraAvailble:available userId:userId]; } -- (void)onOtherClientAccept { - [UIApplication.sharedApplication.keyWindow - makeToast:[self localizableWithKey:@"other_client_accept"]]; - [self destroy]; +- (void)onCallConnected:(NECallInfo *)info { + [self updateUIonStatus:NERtcCallStatusInCall]; + [self stopCurrentPlaying]; + [self startTimer]; } -- (void)onOtherClientReject { - [UIApplication.sharedApplication.keyWindow - makeToast:[self localizableWithKey:@"other_client_reject"]]; +- (void)onCallEnd:(NECallEndInfo *)info { + switch (info.reasonCode) { + case TerminalCodeTimeOut: + [self playRingWithType:CRTNoResponseRing]; + if ([[NetManager shareInstance] isClose] == YES) { + [self destroy]; + return; + } + if (self.callParam.isCaller == YES) { + [self showToastWithContent:[self localizableWithKey:@"remote_timeout"]]; + } + break; + case TerminalCodeBusy: + [self showToastWithContent:[self localizableWithKey:@"remote_busy"]]; + [self playRingWithType:CRTBusyRing]; + break; + + case TerminalCalleeCancel: + [self showToastWithContent:[self localizableWithKey:@"remote_cancel"]]; + break; + + case TerminalCallerRejcted: + [self showToastWithContent:[self localizableWithKey:@"remote_reject"]]; + [self playRingWithType:CRTRejectRing]; + break; + + case TerminalOtherRejected: + [self.preiousWindow ne_makeToast:[self localizableWithKey:@"other_client_reject"]]; + break; + + case TerminalOtherAccepted: + [self.preiousWindow ne_makeToast:[self localizableWithKey:@"other_client_accept"]]; + break; + + case TerminalCallerCancel: + + return; + + default: + break; + } + YXAlogInfo(@"call view controller oncallend : %@", [info yx_modelToJSONString]); [self destroy]; } -- (void)onCallTypeChange:(NERtcCallType)callType withState:(NERtcSwitchState)state { - NSLog(@"onCallTypeChange: %lu withState: %lu", (unsigned long)callType, (unsigned long)state); - switch (state) { - case NERtcSwitchStateAgree: +- (void)onCallTypeChange:(NECallTypeChangeInfo *)info { + NSLog(@"V2 onCallTypeChange : %@", [info yx_modelToJSONString]); + switch (info.state) { + case NECallSwitchStateAgree: [self hideBannerView]; - [self onCallTypeChange:callType]; + [self onCallTypeChangeWithType:info.callType]; break; - case NERtcSwitchStateInvite: { + case NECallSwitchStateInvite: { if (self.alert != nil) { NSLog(@"alert is showing"); return; } UIAlertController *alert = [UIAlertController alertControllerWithTitle:[self localizableWithKey:@"permission"] - message:callType == NERtcCallTypeVideo + message:info.callType == NECallTypeVideo ? [self localizableWithKey:@"audio_to_video"] : [self localizableWithKey:@"video_to_audio"] preferredStyle:UIAlertControllerStyleAlert]; self.alert = alert; - UIAlertAction *rejectAction = - [UIAlertAction actionWithTitle:[self localizableWithKey:@"reject"] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *_Nonnull action) { - [[NERtcCallKit sharedInstance] - switchCallType:callType - withState:NERtcSwitchStateReject - completion:^(NSError *_Nullable error) { - if (error) { - [UIApplication.sharedApplication.keyWindow - makeToast:error.localizedDescription]; - } - }]; - }]; __weak typeof(self) weakSelf = self; - UIAlertAction *agreeAction = - [UIAlertAction actionWithTitle:[self localizableWithKey:@"agree"] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *_Nonnull action) { - [[NERtcCallKit sharedInstance] - switchCallType:callType - withState:NERtcSwitchStateAgree - completion:^(NSError *_Nullable error) { - [weakSelf onCallTypeChange:callType]; - if (error) { - [UIApplication.sharedApplication.keyWindow - makeToast:error.localizedDescription]; - } - }]; - }]; + + UIAlertAction *rejectAction = [UIAlertAction + actionWithTitle:[self localizableWithKey:@"reject"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + NESwitchParam *param = [[NESwitchParam alloc] init]; + param.callType = info.callType; + param.state = NECallSwitchStateReject; + [[NECallEngine sharedInstance] + switchCallType:param + completion:^(NSError *_Nullable error) { + if (error) { + [weakSelf.view ne_makeToast:error.localizedDescription]; + } + }]; + }]; + UIAlertAction *agreeAction = [UIAlertAction + actionWithTitle:[self localizableWithKey:@"agree"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *_Nonnull action) { + NESwitchParam *param = [[NESwitchParam alloc] init]; + param.callType = info.callType; + param.state = NECallSwitchStateAgree; + [[NECallEngine sharedInstance] + switchCallType:param + completion:^(NSError *_Nullable error) { + [weakSelf onCallTypeChangeWithType:info.callType]; + if (error) { + [weakSelf.view ne_makeToast:error.localizedDescription]; + } else { + if (weakSelf.createPipSEL != nil && + weakSelf.status == NECallStatusInCall) { + if (info.callType == NECallTypeVideo) { + [NERtcCallUIKit.sharedInstance + performSelector:weakSelf.createPipSEL]; + } else { + [NERtcCallUIKit.sharedInstance + performSelector:weakSelf.stopPipSEL]; + } + } + } + }]; + }]; [alert addAction:rejectAction]; [alert addAction:agreeAction]; - [self presentViewController:alert animated:YES completion:nil]; - - NSLog(@"NERtcSwitchStateInvite : %ld", callType); + if (self.isSmallWindow == YES) { + UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow; + [keyWindow.rootViewController presentViewController:alert animated:YES completion:nil]; + } else { + [self presentViewController:alert animated:YES completion:nil]; + } + NSLog(@"NERtcSwitchStateInvite : %ld", info.callType); } break; - case NERtcSwitchStateReject: + case NECallSwitchStateReject: [self hideBannerView]; - [UIApplication.sharedApplication.keyWindow makeToast:[self localizableWithKey:@"reject_tip"]]; + [self.view ne_makeToast:[self localizableWithKey:@"reject_tip"]]; break; default: break; } - NSLog(@"onCallTypeChange : %lu with state : %lu", callType, state); -} - -- (void)onCallTypeChange:(NERtcCallType)callType { - NSLog(@"onCallTypeChange:"); - if (self.callType == callType) { - return; - } - self.callType = callType; - [self updateUIonStatus:self.status]; - - if (self.status == NERtcCallStatusInCall) { - switch (callType) { - case NERtcCallTypeAudio: - NSLog(@"NERtcCallTypeAudio"); - [self.operationView changeAudioStyle]; - [self hideVideoView]; - break; - case NERtcCallTypeVideo: - NSLog(@"NERtcCallTypeVideo"); - [self.operationView changeVideoStyle]; - [self showVideoView]; - break; - default: - break; - } - return; - } - - switch (callType) { - case NERtcCallTypeAudio: - [self.operationView changeAudioStyle]; - [self setSwitchVideoStyle]; - break; - case NERtcCallTypeVideo: - [self.operationView changeVideoStyle]; - [self setSwitchAudioStyle]; - break; - default: - break; - } -} - -- (void)onError:(NSError *)error { - NSLog(@"call kit on error : %@", error); -} - -- (void)onAudioAvailable:(BOOL)available userID:(NSString *)userID { - NSLog(@"onAudioAvailable"); } #pragma mark - private mothed + - (void)cameraAvailble:(BOOL)available userId:(NSString *)userId { if ([self.videoInCallController.bigVideoView.userID isEqualToString:userId]) { self.videoInCallController.bigVideoView.maskView.hidden = available; - self.remoteCameraAvailable = available; } if ([self.videoInCallController.smallVideoView.userID isEqualToString:userId]) { self.videoInCallController.smallVideoView.maskView.hidden = available; - self.remoteCameraAvailable = available; + } + + if (self.showMyBigView) { + [self changeRemoteMute:self.isRemoteMute videoView:self.stateUIController.smallVideoView]; + } else { + [self changeRemoteMute:self.isRemoteMute videoView:self.stateUIController.bigVideoView]; + } + if ([userId isEqualToString:self.callParam.remoteUserAccid] && self.isSmallWindow == YES && + self.callParam.callType == NECallTypeVideo) { + self.maskView.hidden = available; } } - (void)setUrl:(NSString *)url withPlaceholder:(NSString *)holder { __weak typeof(self) weakSelf = self; UIImageView *remoteAvatorView = nil; - if (self.callType == NERtcCallTypeVideo) { + if (self.callParam.callType == NECallTypeVideo) { remoteAvatorView = self.videoCallingController.remoteAvatorView; } else { remoteAvatorView = self.calledController.remoteBigAvatorView; } - [remoteAvatorView - sd_setImageWithURL:[NSURL URLWithString:url] - completed:^(UIImage *_Nullable image, NSError *_Nullable error, - SDImageCacheType cacheType, NSURL *_Nullable imageURL) { - __strong typeof(self) strongSelf = weakSelf; - if (image == nil) { - image = [UIImage imageNamed:holder - inBundle:strongSelf.bundle - compatibleWithTraitCollection:nil]; - } - if (strongSelf.isCaller == false && strongSelf.callType == NERtcCallTypeVideo) { - [strongSelf.blurImage setHidden:NO]; - } - strongSelf.blurImage.image = image; - }]; + [remoteAvatorView sd_setImageWithURL:[NSURL URLWithString:url] + completed:^(UIImage *_Nullable image, NSError *_Nullable error, + SDImageCacheType cacheType, NSURL *_Nullable imageURL) { + if (image == nil) { + image = [UIImage imageNamed:holder + inBundle:weakSelf.bundle + compatibleWithTraitCollection:nil]; + } + if (weakSelf.callParam.isCaller == false && + weakSelf.callParam.callType == NECallTypeVideo) { + [weakSelf.blurImage setHidden:NO]; + } + weakSelf.blurImage.image = image; + }]; } - (void)startTimer { @@ -873,6 +935,7 @@ - (void)startTimer { - (void)figureTimer { self.timerCount++; self.timerLabel.text = [self timeFormatted:self.timerCount]; + self.audioSmallViewTimerLabel.text = self.timerLabel.text; } - (NSString *)timeFormatted:(int)totalSeconds { @@ -888,8 +951,9 @@ - (NSString *)timeFormatted:(int)totalSeconds { } - (NSString *)getInviteText { - return (self.callType == NERtcCallTypeAudio ? [self localizableWithKey:@"invite_audio_call"] - : [self localizableWithKey:@"invite_video_call"]); + return (self.callParam.callType == NECallTypeAudio + ? [self localizableWithKey:@"invite_audio_call"] + : [self localizableWithKey:@"invite_video_call"]); } - (void)hideBannerView { @@ -900,30 +964,46 @@ - (void)showBannerView { self.bannerView.hidden = NO; } +- (void)changeToNormal { + [super changeToNormal]; + if (self.callParam.callType == NECallTypeVideo) { + [self.videoInCallController refreshVideoView]; + } +} + #pragma mark - destroy - (void)destroy { if (self.alert != nil) { [self.alert dismissViewControllerAnimated:NO completion:nil]; } + [self stopCurrentPlaying]; [[NSNotificationCenter defaultCenter] postNotificationName:kCallKitDismissNoti object:nil]; - [[NERtcCallKit sharedInstance] removeDelegate:self]; + [[NECallEngine sharedInstance] removeCallDelegate:self]; if (self.timer != nil) { [self.timer invalidate]; self.timer = nil; } + [self stopCurrentPlaying]; } #pragma mark - property -- (UILabel *)cnameLabel { - if (_cnameLabel == nil) { - _cnameLabel = [[UILabel alloc] init]; - _cnameLabel.textColor = [UIColor redColor]; - _cnameLabel.font = [UIFont systemFontOfSize:14]; - _cnameLabel.translatesAutoresizingMaskIntoConstraints = NO; +/// 最小化按钮 +- (UIButton *)smallButton { + if (!_smallButton) { + _smallButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _smallButton.translatesAutoresizingMaskIntoConstraints = NO; + [_smallButton setImage:[UIImage imageNamed:@"small_button" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateNormal]; + _smallButton.hidden = YES; + [_smallButton addTarget:self + action:@selector(changeToSmall) + forControlEvents:UIControlEventTouchUpInside]; } - return _cnameLabel; + return _smallButton; } - (UIView *)bannerView { @@ -958,7 +1038,7 @@ - (UIView *)bannerView { label.textColor = [UIColor whiteColor]; [NSLayoutConstraint activateConstraints:@[ [label.leftAnchor constraintEqualToAnchor:self.bannerView.leftAnchor constant:10], - [label.topAnchor constraintEqualToAnchor:self.bannerView.topAnchor], + [label.centerYAnchor constraintEqualToAnchor:self.bannerView.centerYAnchor], [label.rightAnchor constraintEqualToAnchor:closeBtn.leftAnchor constant:-10] ]]; @@ -987,6 +1067,7 @@ - (UIButton *)switchCameraBtn { - (NEVideoOperationView *)operationView { if (!_operationView) { _operationView = [[NEVideoOperationView alloc] init]; + _operationView.enableVirtualBackground = self.callParam.enableVirtualBackground; _operationView.translatesAutoresizingMaskIntoConstraints = NO; _operationView.layer.cornerRadius = 30; [_operationView.microPhone addTarget:self @@ -1004,6 +1085,9 @@ - (NEVideoOperationView *)operationView { [_operationView.speakerBtn addTarget:self action:@selector(operationSpeakerClick:) forControlEvents:UIControlEventTouchUpInside]; + [_operationView.virtualBtn addTarget:self + action:@selector(virtualBackgroundBtnClick:) + forControlEvents:UIControlEventTouchUpInside]; } return _operationView; } @@ -1020,7 +1104,7 @@ - (UILabel *)timerLabel { } - (void)dealloc { - [[NERtcCallKit sharedInstance] removeDelegate:self]; + [[NECallEngine sharedInstance] removeCallDelegate:self]; } - (void)hideViews:(NSArray *)views { @@ -1036,37 +1120,34 @@ - (void)showViews:(NSArray *)views { } - (void)changeDefaultImage:(BOOL)mute { - // TODO: 代码整理 - /* - UIImage *image = [[SettingManager shareInstance] muteDefaultImage]; - if (image != nil) { - if (mute == YES) { - if (self.showMyBigView) { - self.bigVideoView.imageView.image = image; - self.bigVideoView.imageView.hidden = NO; - [self changeRemoteMute:self.isRemoteMute videoView:self.smallVideoView]; - } else { - self.smallVideoView.imageView.image = image; - self.smallVideoView.imageView.hidden = NO; - [self changeRemoteMute:self.isRemoteMute videoView:self.bigVideoView]; - } - } else { - if (self.showMyBigView) { - self.bigVideoView.imageView.image = nil; - self.bigVideoView.imageView.hidden = YES; - self.smallVideoView.imageView.hidden = YES; - [self changeRemoteMute:self.isRemoteMute videoView:self.smallVideoView]; - } else { - self.smallVideoView.imageView.image = nil; - self.smallVideoView.imageView.hidden = YES; - [self changeRemoteMute:self.isRemoteMute videoView:self.bigVideoView]; - } - } - } */ + NSLog(@"changeDefaultImage mute : %d", mute); + NSLog(@"showMyBigView : %d", self.showMyBigView); + + UIImage *image = self.callParam.muteDefaultImage; + if (image != nil) { + if (mute == YES) { + if (self.showMyBigView) { + self.stateUIController.bigVideoView.imageView.image = image; + self.stateUIController.bigVideoView.imageView.hidden = NO; + } else { + self.stateUIController.smallVideoView.imageView.image = image; + self.stateUIController.smallVideoView.imageView.hidden = NO; + } + } else { + if (self.showMyBigView) { + self.stateUIController.bigVideoView.imageView.image = nil; + self.stateUIController.bigVideoView.imageView.hidden = YES; + self.stateUIController.smallVideoView.imageView.hidden = YES; + } else { + self.stateUIController.smallVideoView.imageView.image = nil; + self.stateUIController.smallVideoView.imageView.hidden = YES; + } + } + } } - (void)changeRemoteMute:(BOOL)mute videoView:(NEVideoView *)remoteVideo { - UIImage *defaultImage = [[SettingManager shareInstance] remoteDefaultImage]; + UIImage *defaultImage = self.callParam.remoteDefaultImage; if (mute == true && defaultImage != nil) { remoteVideo.imageView.hidden = NO; remoteVideo.imageView.image = defaultImage; @@ -1082,11 +1163,10 @@ - (NEAudioCallingController *)audioCallingController { } if (nil == _audioCallingController) { _audioCallingController = [[NEAudioCallingController alloc] init]; - _audioCallingController.isCaller = self.isCaller; _audioCallingController.callParam = self.callParam; - _audioCallingController.callType = self.callType; _audioCallingController.mainController = self; _audioCallingController.view.hidden = YES; + _audioCallingController.operationView = self.operationView; } return _audioCallingController; @@ -1099,11 +1179,10 @@ - (NEAudioInCallController *)audioInCallController { } if (nil == _audioInCallController) { _audioInCallController = [[NEAudioInCallController alloc] init]; - _audioInCallController.isCaller = self.isCaller; _audioInCallController.callParam = self.callParam; - _audioInCallController.callType = self.callType; _audioInCallController.mainController = self; _audioInCallController.view.hidden = YES; + _audioInCallController.operationView = self.operationView; } return _audioInCallController; } @@ -1115,11 +1194,10 @@ - (NEVideoCallingController *)videoCallingController { } if (nil == _videoCallingController) { _videoCallingController = [[NEVideoCallingController alloc] init]; - _videoCallingController.isCaller = self.isCaller; _videoCallingController.callParam = self.callParam; - _videoCallingController.callType = self.callType; _videoCallingController.mainController = self; _videoCallingController.view.hidden = YES; + _videoCallingController.operationView = self.operationView; } return _videoCallingController; } @@ -1131,9 +1209,7 @@ - (NEVideoInCallController *)videoInCallController { } if (nil == _videoInCallController) { _videoInCallController = [[NEVideoInCallController alloc] init]; - _videoInCallController.isCaller = self.isCaller; _videoInCallController.callParam = self.callParam; - _videoInCallController.callType = self.callType; _videoInCallController.mainController = self; _videoInCallController.view.hidden = YES; } @@ -1147,9 +1223,7 @@ - (NECalledViewController *)calledController { } if (nil == _calledController) { _calledController = [[NECalledViewController alloc] init]; - _calledController.isCaller = self.isCaller; _calledController.callParam = self.callParam; - _calledController.callType = self.callType; _calledController.mainController = self; _calledController.view.hidden = YES; } @@ -1162,10 +1236,9 @@ - (NECallUIStateController *)getCallStateInstanceWithClassKey:(NSString *)key { Class cls = [self.uiConfigDic objectForKey:key]; if (nil != cls) { NECallUIStateController *controller = [[cls alloc] init]; - controller.isCaller = self.isCaller; controller.callParam = self.callParam; - controller.callType = self.callType; controller.mainController = self; + controller.operationView = self.operationView; controller.view.hidden = YES; return controller; } @@ -1196,6 +1269,27 @@ - (UIView *)getDefaultHeaderView:(NSString *)accid - (NSString *)localizableWithKey:(NSString *)key { return [self.bundle localizedStringForKey:key value:nil table:@"Localizable"]; - ; } + +#pragma mark CallEngine Key Value + +- (BOOL)isGlobalInit { + return !([[[NECallEngine sharedInstance] valueForKeyPath:@"context.initRtcMode"] intValue] == 1); +} + +- (BOOL)isSupportAutoJoinWhenCalled { + return [[[NECallEngine sharedInstance] valueForKeyPath:@"context.supportAutoJoinWhenCalled"] + boolValue]; +} + +#pragma mark Other Delegate +- (void)onNERtcEngineVirtualBackgroundSourceEnabled:(BOOL)enabled + reason: + (NERtcVirtualBackgroundSourceStateReason)reason { + if (reason == kNERtcVirtualBackgroundSourceStateReasonDeviceNotSupported) { + [self.view ne_makeToast:[self localizableWithKey:@"device_not_support"]]; + self.operationView.virtualBtn.selected = NO; + } +} + @end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.h index 72cbca29..b7aacbd6 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.h +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.h @@ -8,6 +8,10 @@ NS_ASSUME_NONNULL_BEGIN @interface NECalledViewController : NECallUIStateController +@property(nonatomic, strong) UILabel *connectingLabel; + +- (void)checkCallePreview; + @end NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.m index 81a49ddb..c2e1d247 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NECalledViewController.m @@ -3,9 +3,12 @@ // found in the LICENSE file. #import "NECalledViewController.h" +#import @interface NECalledViewController () +@property(nonatomic, strong) UIView *preView; + @end @implementation NECalledViewController @@ -16,7 +19,16 @@ - (void)viewDidLoad { } - (void)setupUI { - [super setupUI]; + [self.view addSubview:self.preView]; + [NSLayoutConstraint activateConstraints:@[ + [self.preView.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [self.preView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor], + [self.preView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor], + [self.preView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] + ]]; + + [self checkCallePreview]; + /// 接听和拒接按钮 [self.view addSubview:self.rejectBtn]; [NSLayoutConstraint activateConstraints:@[ @@ -40,6 +52,19 @@ - (void)setupUI { [self setupCenterRemoteAvator]; + self.connectingLabel = [[UILabel alloc] init]; + self.connectingLabel.translatesAutoresizingMaskIntoConstraints = NO; + self.connectingLabel.text = [self localizableWithKey:@"connecting"]; + self.connectingLabel.textColor = [UIColor whiteColor]; + self.connectingLabel.font = [UIFont systemFontOfSize:14]; + self.connectingLabel.hidden = YES; + [self.view addSubview:self.connectingLabel]; + [NSLayoutConstraint activateConstraints:@[ + [self.connectingLabel.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor], + [self.connectingLabel.bottomAnchor constraintEqualToAnchor:self.acceptBtn.topAnchor + constant:-20], + ]]; + [self refreshUI]; } @@ -50,6 +75,51 @@ - (void)refreshUI { self.centerSubtitleLabel.text = [self getInviteText]; } +- (void)checkCallePreview { + if (self.callParam.isCaller == NO && self.callParam.enableCalleePreview && + self.callParam.callType == NECallTypeVideo && + [[[NECallEngine sharedInstance] valueForKeyPath:@"context.initRtcMode"] intValue] != + InitRtcInNeedDelayToAccept) { + self.preView.hidden = NO; + NSLog(@"called preview"); + + __weak typeof(self) weakSelf = self; + + AVAuthorizationStatus authorizationStatus = + [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; + if (authorizationStatus == AVAuthorizationStatusNotDetermined) { + // 请求摄像头权限 + [AVCaptureDevice + requestAccessForMediaType:AVMediaTypeVideo + completionHandler:^(BOOL granted) { + if (granted) { + if (weakSelf != nil) { + [[NECallEngine sharedInstance] setupLocalView:weakSelf.preView]; + } + } else { + // 用户未授权 + } + }]; + } else if (authorizationStatus == AVAuthorizationStatusAuthorized) { + if (weakSelf != nil) { + [[NECallEngine sharedInstance] setupLocalView:weakSelf.preView]; + } + } else { + // 用户未授权 + } + } else { + self.preView.isHidden; + } +} + +- (UIView *)preView { + if (nil == _preView) { + _preView = [[UIView alloc] init]; + _preView.translatesAutoresizingMaskIntoConstraints = NO; + } + return _preView; +} + /* #pragma mark - Navigation diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.m index 9501ad54..f680016c 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoCallingController.m @@ -26,19 +26,6 @@ - (void)setupUI { [self.bigVideoView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] ]]; - // [self.view addSubview:self.smallVideoView]; - // [NSLayoutConstraint activateConstraints:@[ - // [self.smallVideoView.topAnchor constraintEqualToAnchor:self.view.topAnchor - // constant:self.statusHeight + 20], - // [self.smallVideoView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor - // constant:-20], [self.smallVideoView.heightAnchor constraintEqualToConstant:160], - // [self.smallVideoView.widthAnchor constraintEqualToConstant:90] - // ]]; - // - // self.smallVideoView.clipsToBounds = YES; - // self.smallVideoView.layer.cornerRadius = self.radius; - // self.smallVideoView.hidden = YES; - [self.view addSubview:self.remoteAvatorView]; [NSLayoutConstraint activateConstraints:@[ [self.remoteAvatorView.topAnchor constraintEqualToAnchor:self.view.topAnchor diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.m index 618160b6..53f024e8 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Controller/NEVideoInCallController.m @@ -16,7 +16,6 @@ - (void)viewDidLoad { } - (void)setupUI { - [super setupUI]; [self.view addSubview:self.bigVideoView]; [NSLayoutConstraint activateConstraints:@[ [self.bigVideoView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor], diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NERingPlayerManager.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NERingPlayerManager.h new file mode 100644 index 00000000..4e4d785c --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NERingPlayerManager.h @@ -0,0 +1,27 @@ +//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +typedef NS_ENUM(NSInteger, CallRingType) { + CRTCallerRing = 1, // 主叫呼叫铃声 + CRTCalleeRing = 2, // 被叫收到邀请铃声 + CRTRejectRing = 3, // 拒绝接听铃声 + CRTBusyRing = 4, // 拒绝接听铃声 + CRTNoResponseRing = 5, // 无响应铃声 +}; + +NS_ASSUME_NONNULL_BEGIN + +@interface NERingPlayerManager : NSObject + ++ (id)shareInstance; + +- (void)playRingWithRingType:(CallRingType)ringType isRtcPlay:(Boolean)isRtc; + +- (void)stopCurrentPlaying; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NERingPlayerManager.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NERingPlayerManager.m new file mode 100644 index 00000000..54b45798 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NERingPlayerManager.m @@ -0,0 +1,128 @@ +//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NERingPlayerManager.h" +#import +#import "NERtcCallUIKit.h" + +@interface NERingPlayerManager () + +/// 播放伴音的id +@property(nonatomic, strong) NSMutableArray *ids; + +/// 播放器 +@property(nonatomic, strong) AVAudioPlayer *player; + +@end + +@implementation NERingPlayerManager + ++ (id)shareInstance { + static NERingPlayerManager *shareInstance = nil; + static dispatch_once_t once_token; + dispatch_once(&once_token, ^{ + if (!shareInstance) { + shareInstance = [[self alloc] init]; + } + }); + return shareInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.ids = [[NSMutableArray alloc] init]; + } + return self; +} + +- (void)stopCurrentPlaying { + if ([self.player isPlaying]) { + NSLog(@"stopCurrentPlaying"); + [self.player stop]; + self.player = nil; + } +} + +- (void)playRingWithRingType:(CallRingType)ringType isRtcPlay:(Boolean)isRtc { + switch (ringType) { + case CRTCallerRing: + [self playerWithPath:[NERtcCallUIKit sharedInstance].ringFile.callerRingFilePath + isRtcPlay:isRtc + isRepeat:YES]; + break; + case CRTCalleeRing: + [self playerWithPath:[NERtcCallUIKit sharedInstance].ringFile.calleeRingFilePath + isRtcPlay:isRtc + isRepeat:YES]; + break; + + case CRTRejectRing: + [self playerWithPath:[NERtcCallUIKit sharedInstance].ringFile.rejectRingFilePath + isRtcPlay:isRtc + isRepeat:NO]; + break; + + case CRTBusyRing: + [self playerWithPath:[NERtcCallUIKit sharedInstance].ringFile.busyRingFilePath + isRtcPlay:isRtc + isRepeat:NO]; + break; + + case CRTNoResponseRing: + [self playerWithPath:[NERtcCallUIKit sharedInstance].ringFile.noResponseFilePath + isRtcPlay:isRtc + isRepeat:NO]; + break; + default: + break; + } +} + +- (void)playerWithPath:(NSString *)path isRtcPlay:(BOOL)isRtc isRepeat:(BOOL)repeat { + NSURL *url = nil; + if ([path hasPrefix:@"http"]) { + url = [NSURL URLWithString:path]; + } else if (path.length > 0) { + url = [NSURL fileURLWithPath:path]; + } + + if (url != nil) { + [self stopCurrentPlaying]; + [self resetAuidoSessionCategory]; + dispatch_async(dispatch_get_main_queue(), ^{ + NSError *error = nil; + self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; + self.player.delegate = self; + if (repeat == YES) { + self.player.numberOfLoops = -1; + } else { + self.player.numberOfLoops = 1; + } + + if (error == nil) { + BOOL isPlay = [self.player play]; + NSLog(@"player play result : %d", isPlay); + } else { + NSLog(@"callkit audio player init error : %@", error.localizedDescription); + } + }); + } +} + +- (void)resetAuidoSessionCategory { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session setActive:YES error:nil]; + [session setCategory:AVAudioSessionCategoryPlayback error:nil]; +} + +#pragma mark - delegate + +- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error { +} + +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.m index fdf3009c..cde5dc97 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/NetManager.m @@ -3,7 +3,7 @@ // found in the LICENSE file. #import "NetManager.h" -#import "AFNetworking.h" +#import @implementation NetManager @@ -28,25 +28,25 @@ - (instancetype)init { #pragma mark - 监测网络状态 - (void)monitorNetworkState { - AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager]; + YXNetworkReachabilityManager *manager = [YXNetworkReachabilityManager sharedManager]; [manager startMonitoring]; self.isClose = [manager isReachable] ? NO : YES; NSLog(@"net work close state : %d", self.isClose); - [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { + [manager setReachabilityStatusChangeBlock:^(YXNetworkReachabilityStatus status) { switch (status) { - case AFNetworkReachabilityStatusNotReachable: + case YXNetworkReachabilityStatusNotReachable: NSLog(@"没有网络"); self.isClose = YES; break; - case AFNetworkReachabilityStatusUnknown: + case YXNetworkReachabilityStatusUnknown: NSLog(@"未知"); self.isClose = YES; break; - case AFNetworkReachabilityStatusReachableViaWiFi: + case YXNetworkReachabilityStatusReachableViaWiFi: NSLog(@"WiFi"); self.isClose = NO; break; - case AFNetworkReachabilityStatusReachableViaWWAN: + case YXNetworkReachabilityStatusReachableViaWWAN: NSLog(@"3G|4G"); self.isClose = NO; break; diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.h deleted file mode 100644 index 67e510d0..00000000 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SettingManager : NSObject - -@property(nonatomic, assign, readonly) NSInteger timeout; - -@property(nonatomic, assign, readonly) BOOL supportAutoJoinWhenCalled; - -@property(nonatomic, assign, readonly) BOOL rejectBusyCode; - -@property(nonatomic, assign, readonly) BOOL openCustomTokenAndChannelName; - -@property(nonatomic, assign) uint64_t customUid; - -@property(nonatomic, strong) NSString *customChannelName; - -@property(nonatomic, strong) NSString *customToken; - -@property(nonatomic, strong) NSString *globalExtra; - -@property(nonatomic, assign) BOOL isAudioConfirm; - -@property(nonatomic, assign) BOOL isJoinRtcWhenCall; - -@property(nonatomic, assign) BOOL isVideoConfirm; - -@property(nonatomic, assign, readonly) bool incallShowCName; - -@property(nonatomic, strong, nullable) UIImage *muteDefaultImage; - -@property(nonatomic, strong, nullable) UIImage *remoteDefaultImage; - -@property(nonatomic, assign) BOOL isGroupPush; - -@property(nonatomic, strong) NSString *customPushContent; - -@property(nonatomic, assign, readonly) BOOL isGlobalInit; - -@property(nonatomic, assign, readonly) BOOL useEnableLocalMute; - -+ (id)shareInstance; - -- (void)setTimeoutWithSecond:(NSInteger)second; - -- (void)setAutoJoin:(BOOL)autoJoin; - -- (void)setBusyCode:(BOOL)open; - -- (void)setCallKitUid:(uint64_t)uid; - -- (void)setShowCName:(BOOL)show; - -- (NSString *)getRtcCName; - -- (uint64_t)getCallKitUid; - -- (void)setEnableLocal:(BOOL)enable; - -- (void)setIsGlobalInit:(BOOL)isGlobalInit - withApnsCer:(NSString *)apnsCer - withAppkey:(NSString *)appkey; - -@end - -NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.m deleted file mode 100644 index 40f2bcf4..00000000 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Manager/SettingManager.m +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -#import "SettingManager.h" -#import -NSString *const kYXOTOTimeOut = @"kYXOTOTimeOut"; - -NSString *const kShowCName = @"kShowCName"; - -@interface SettingManager () - -@property(nonatomic, assign, readwrite) NSInteger timeout; - -@property(nonatomic, assign, readwrite) BOOL supportAutoJoinWhenCalled; - -@property(nonatomic, assign, readwrite) BOOL rejectBusyCode; - -@property(nonatomic, assign, readwrite) BOOL openCustomTokenAndChannelName; - -@property(nonatomic, assign, readwrite) bool incallShowCName; - -@property(nonatomic, assign, readwrite) BOOL useEnableLocalMute; - -@property(nonatomic, assign, readwrite) BOOL isGlobalInit; - -@end - -@implementation SettingManager - -+ (id)shareInstance { - static SettingManager *shareInstance = nil; - static dispatch_once_t once_token; - dispatch_once(&once_token, ^{ - if (!shareInstance) { - shareInstance = [[self alloc] init]; - } - }); - return shareInstance; -} - -- (void)setCallKitUid:(uint64_t)uid { - [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithUnsignedLongLong:uid] - forKeyPath:@"context.currentUserUid"]; - - // if ([[NERtcCallKit sharedInstance] respondsToSelector:@selector(changeStatusIdle)]) { - // [[NERtcCallKit sharedInstance] changeStatusIdle]; - // } -} - -- (uint64_t)getCallKitUid { - return [[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.currentUserUid"] - unsignedLongLongValue]; -} - -- (void)setAutoJoin:(BOOL)autoJoin { - [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:autoJoin] - forKeyPath:@"context.supportAutoJoinWhenCalled"]; - self.supportAutoJoinWhenCalled = autoJoin; -} - -- (void)setBusyCode:(BOOL)open { - self.rejectBusyCode = open; -} - -- (instancetype)init { - self = [super init]; - if (self) { - self.isGroupPush = YES; - self.supportAutoJoinWhenCalled = [[[NERtcCallKit sharedInstance] - valueForKeyPath:@"context.supportAutoJoinWhenCalled"] boolValue]; - self.rejectBusyCode = NO; - NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; - NSNumber *showCname = [userDefault objectForKey:kShowCName]; - if (showCname != nil) { - self.incallShowCName = [showCname boolValue]; - } - NSLog(@"current accid : %@", NIMSDK.sharedSDK.loginManager.currentAccount); - } - return self; -} - -- (void)setTimeoutWithSecond:(NSInteger)second { - [[NERtcCallKit sharedInstance] setTimeOutSeconds:second]; -} - -- (NSInteger)timeout { - return [[NERtcCallKit sharedInstance] timeOutSeconds]; -} - -- (BOOL)isGlobalInit { - return ![[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.globalInit"] boolValue]; -} - -- (void)setIsGlobalInit:(BOOL)isGlobalInit - withApnsCer:(NSString *)apnsCer - withAppkey:(NSString *)appkey { - [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:!isGlobalInit] - forKeyPath:@"context.globalInit"]; - if (isGlobalInit == NO) { - NERtcCallOptions *option = [NERtcCallOptions new]; - option.APNSCerName = apnsCer; - option.disableRecord = NO; - option.joinRtcWhenCall = [self isJoinRtcWhenCall]; - option.globalInit = YES; - NERtcCallKit *callkit = [NERtcCallKit sharedInstance]; - option.supportAutoJoinWhenCalled = self.supportAutoJoinWhenCalled; - [callkit setupAppKey:appkey options:option]; - } else { - [NERtcEngine destroyEngine]; - } -} - -- (BOOL)isJoinRtcWhenCall { - return [[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.joinRtcWhenCall"] boolValue]; -} - -- (void)setIsJoinRtcWhenCall:(BOOL)isJoinRtcWhenCall { - [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:isJoinRtcWhenCall] - forKeyPath:@"context.joinRtcWhenCall"]; -} - -- (BOOL)isAudioConfirm { - return [[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.confirmAudio"] boolValue]; -} - -- (void)setIsAudioConfirm:(BOOL)isAudioConfirm { - [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:isAudioConfirm] - forKeyPath:@"context.confirmAudio"]; -} - -- (BOOL)isVideoConfirm { - return [[[NERtcCallKit sharedInstance] valueForKeyPath:@"context.confirmVideo"] boolValue]; -} - -- (void)setIsVideoConfirm:(BOOL)isVideoConfirm { - [[NERtcCallKit sharedInstance] setValue:[NSNumber numberWithBool:isVideoConfirm] - forKeyPath:@"context.confirmVideo"]; -} - -- (NSString *)getRtcCName { - return [[NERtcCallKit sharedInstance] valueForKeyPath:@"context.channelInfo.channelName"]; -} - -- (void)setShowCName:(BOOL)show { - self.incallShowCName = show; - NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; - [userDefault setObject:[NSNumber numberWithBool:show] forKey:kShowCName]; - [userDefault synchronize]; -} - -// 1.5.6 add -- (void)setEnableLocal:(BOOL)enable { - self.useEnableLocalMute = enable; -} - -@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.h deleted file mode 100644 index ace9ddb5..00000000 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NECallParam : NSObject - -#pragma mark - 必要参数 -// 被叫accid -@property(nonatomic, strong) NSString *remoteUserAccid; -// 主叫accid -@property(nonatomic, strong) NSString *currentUserAccid; -// 通话页面被叫显示名称 -@property(nonatomic, strong) NSString *remoteShowName; -// 被叫头像链接 -@property(nonatomic, strong) NSString *remoteAvatar; -// 呼叫类型 -@property(assign, nonatomic) NERtcCallType callType; - -#pragma mark - 可选自定义参数 -@property(nonatomic, strong) NSString *token; -@property(nonatomic, strong) NSString *extra; -@property(nonatomic, strong) NSString *channelName; -@property(nonatomic, strong) NSString *attachment; - -@end - -NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.m deleted file mode 100644 index 3d6e0ec0..00000000 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NECallParam.m +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -#import "NECallParam.h" - -@implementation NECallParam - -@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NERingFile.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NERingFile.h new file mode 100644 index 00000000..b0879b0a --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NERingFile.h @@ -0,0 +1,31 @@ +//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NERingFile : NSObject + +/// 主叫呼叫提示音 +@property(nonatomic, strong, nullable) NSString *callerRingFilePath; + +/// 被叫收到邀请提示音 +@property(nonatomic, strong, nullable) NSString *calleeRingFilePath; + +/// 拒绝提示音 +@property(nonatomic, strong, nullable) NSString *rejectRingFilePath; + +/// 忙线提示音 +@property(nonatomic, strong, nullable) NSString *busyRingFilePath; + +/// 无响应提示音 +@property(nonatomic, strong, nullable) NSString *noResponseFilePath; + +/// 初始化 +- (instancetype)initWithBundle:(NSBundle *)bundle; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NERingFile.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NERingFile.m new file mode 100644 index 00000000..314b8597 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NERingFile.m @@ -0,0 +1,21 @@ +//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NERingFile.h" + +@implementation NERingFile + +- (instancetype)initWithBundle:(NSBundle *)bundle { + self = [super init]; + if (self) { + self.callerRingFilePath = [bundle pathForResource:@"avchat_connecting" ofType:@"mp3"]; + self.calleeRingFilePath = [bundle pathForResource:@"avchat_ring" ofType:@"mp3"]; + self.busyRingFilePath = [bundle pathForResource:@"avchat_peer_busy" ofType:@"mp3"]; + self.rejectRingFilePath = [bundle pathForResource:@"avchat_peer_reject" ofType:@"mp3"]; + self.noResponseFilePath = [bundle pathForResource:@"avchat_no_response" ofType:@"mp3"]; + } + return self; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NEUICallParam.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NEUICallParam.h new file mode 100644 index 00000000..14907900 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NEUICallParam.h @@ -0,0 +1,85 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NEUICallParam : NSObject + +#pragma mark - 必要参数 + +/// 被叫accid +@property(nonatomic, strong) NSString *remoteUserAccid; + +/// 主叫accid +@property(nonatomic, strong) NSString *currentUserAccid; + +/// 通话页面被叫显示名称 +@property(nonatomic, strong) NSString *remoteShowName; + +/// 被叫头像链接 +@property(nonatomic, strong) NSString *remoteAvatar; + +/// 呼叫类型 +@property(assign, nonatomic) NECallType callType; + +/// 是否是主叫 YES 表示主叫 +@property(nonatomic, assign) BOOL isCaller; + +#pragma mark - 可选自定义参数 + +/// 推送自定义配置 +@property(nonatomic, strong, nullable) NECallPushConfig *pushConfig; + +/// 全局抄送 +@property(nonatomic, strong) NSString *extra; + +/// 自定义channel name +@property(nonatomic, strong) NSString *channelName; + +/// 呼叫扩展参数 +@property(nonatomic, strong) NSString *attachment; + +/// 自定义参数扩展 +@property(nonatomic, strong) id customObject; + +#pragma mark - UI配置参数 + +/// 本端关闭头像默认显示头像 +@property(nonatomic, strong) UIImage *muteDefaultImage; + +/// 远端关闭视频默认显示头像 +@property(nonatomic, strong) UIImage *remoteDefaultImage; + +/// 是否禁止音频通话转视频通话,默认YES,支持转换 +@property(nonatomic, assign) BOOL enableAudioToVideo; + +/// 是否禁止音频通话转视频通话,默认YES,支持转换 +@property(nonatomic, assign) BOOL enableVideoToAudio; + +/// 默认NO,关闭视频画面的时候使用 muteLocalVideo ,设置为YES时候,UI组件关闭视频时调用 +/// enableLocalVideo 设置NO来停止本端视频流 +@property(nonatomic, assign) BOOL useEnableLocalMute; + +/// 是否开启内部话单弹框话单toast +@property(nonatomic, assign) BOOL enableShowRecorderToast; + +/// 是否开启虚化功能,默认NO, 不开启 +@property(nonatomic, assign) BOOL enableVirtualBackground; + +/// 是否开启被叫预览,默认NO,不开启 +@property(nonatomic, assign) BOOL enableCalleePreview; + +/// 是否开启小窗功能,默认不开启 +@property(nonatomic, assign) BOOL enableFloatingWindow; + +/// 是否开启应用外小窗功能,默认不开启,开启后内部会使用 NECallEngine engineDelegate +/// 属性监听Rtc回调,如果已经使用,存在影响,请在外部根据画中画方案实现应用外小窗 +@property(nonatomic, assign) BOOL enableFloatingWindowOutOfApp; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NEUICallParam.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NEUICallParam.m new file mode 100644 index 00000000..5468a8d8 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/Model/NEUICallParam.m @@ -0,0 +1,17 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEUICallParam.h" + +@implementation NEUICallParam + +- (instancetype)init { + self = [super init]; + if (self) { + self.enableShowRecorderToast = YES; + } + return self; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallKitUtil.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallKitUtil.h new file mode 100644 index 00000000..c0e8c2fe --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallKitUtil.h @@ -0,0 +1,15 @@ +//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NECallKitUtil : NSObject + ++ (UIColor *)colorWithHexString:(NSString *)hexString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallKitUtil.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallKitUtil.m new file mode 100644 index 00000000..7a733988 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallKitUtil.m @@ -0,0 +1,22 @@ +//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NECallKitUtil.h" + +@implementation NECallKitUtil + +// 16 进制颜色转换 转换成 UIColor ++ (UIColor *)colorWithHexString:(NSString *)hexString { + unsigned int hexValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; // 跳过字符串开头的# + [scanner scanHexInt:&hexValue]; // 将字符串转换为16进制整数 + UIColor *color = [UIColor colorWithRed:((hexValue & 0xFF0000) >> 16) / 255.0 + green:((hexValue & 0xFF00) >> 8) / 255.0 + blue:(hexValue & 0xFF) / 255.0 + alpha:1.0]; + return color; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallUIKitConfig.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallUIKitConfig.h new file mode 100644 index 00000000..09c9a244 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallUIKitConfig.h @@ -0,0 +1,60 @@ +// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NECallUIConfig : NSObject + +/// 是否禁止音频通话转视频通话,默认YES,支持转换 +@property(nonatomic, assign) BOOL enableAudioToVideo; + +/// 是否禁止音频通话转视频通话,默认YES,支持转换 +@property(nonatomic, assign) BOOL enableVideoToAudio; + +/// 收到呼叫时是否禁止弹出被叫页面,默认NO,弹出被叫页面,用户可以通过此配置禁止组件弹出,自己通过继承以及监听被叫回调实现相关功能 +@property(nonatomic, assign) BOOL disableShowCalleeView; + +/// 通话前音视频切换按钮是否显示,默认NO,不显示,开启此配置前需要开启 NERtcCallOptions 中 +/// supportAutoJoinWhenCalled 属性 +@property(nonatomic, assign) BOOL showCallingSwitchCallType; + +/// 被叫显示昵称字段还是手机号字段,默认显示昵称 +@property(nonatomic, assign) BOOL calleeShowPhone; + +/// 默认NO,关闭视频画面的时候使用 muteLocalVideo ,设置为YES时候,UI组件关闭视频时调用 +/// enableLocalVideo 设置NO来停止本端视频流 +@property(nonatomic, assign) BOOL useEnableLocalMute; + +/// 是否开启小窗功能,默认不开启 +@property(nonatomic, assign) BOOL enableFloatingWindow; + +/// 是否开启应用外小窗功能,默认不开启,开启后内部会使用 NECallEngine engineDelegate +/// 属性监听Rtc回调,如果已经使用,存在影响,请在外部根据画中画方案实现应用外小窗 +@property(nonatomic, assign) BOOL enableFloatingWindowOutOfApp; + +/// 是否开启虚化功能,默认NO, 不开启 +@property(nonatomic, assign) BOOL enableVirtualBackground; + +/// 是否开启被叫预览,默认NO,不开启 +@property(nonatomic, assign) BOOL enableCalleePreview; + +@end + +@interface NECallUIKitConfig : NSObject + +/// 透传 NECallEngine 初始化配置,如果不需要UI组件内部初始化 NECallEngine 则不传此参数即可 +@property(nonatomic, strong, nullable) NESetupConfig *config; + +/// appkey +@property(nonatomic, strong) NSString *appKey; + +/// UI 配置 +@property(nonatomic, strong) NECallUIConfig *uiConfig; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallUIKitConfig.m similarity index 60% rename from NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.m rename to NERtcCallUIKit/NERtcCallUIKit/Classes/NECallUIKitConfig.m index 068e1aea..3fdbd490 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NECallUIKitConfig.m @@ -2,13 +2,22 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -#import "NERtcCallUIConfig.h" +#import "NECallUIKitConfig.h" @implementation NECallUIConfig +- (instancetype)init { + self = [super init]; + if (self) { + self.enableAudioToVideo = YES; + self.enableVideoToAudio = YES; + } + return self; +} + @end -@implementation NERtcCallUIConfig +@implementation NECallUIKitConfig - (NECallUIConfig *)uiConfig { if (nil == _uiConfig) { diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.h deleted file mode 100644 index 624b5a2e..00000000 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIConfig.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2022 NetEase, Inc. All rights reserved. -// Use of this source code is governed by a MIT license that can be -// found in the LICENSE file. - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NECallUIConfig : NSObject - -/// 是否禁止音频通话转视频通话,默认NO,支持转换 -@property(nonatomic, assign) BOOL audioToVideoDisable; - -/// 是否禁止音频通话转视频通话,默认NO,支持转换 -@property(nonatomic, assign) BOOL videoToAudioDisable; - -/// 收到呼叫时是否禁止弹出被叫页面,默认NO,弹出被叫页面,用户可以通过此配置禁止组件弹出,自己通过继承以及监听被叫回调实现相关功能 -@property(nonatomic, assign) BOOL disableShowCalleeView; - -/// 是否初始化路由配置,默认NO,不进行路由初始化配置 -@property(nonatomic, assign) BOOL isInitRouter; - -/// 通话前音视频切换按钮是否显示,默认NO,不显示,开启此配置前需要开启 NERtcCallOptions 中 -/// supportAutoJoinWhenCalled 属性 -@property(nonatomic, assign) BOOL showCallingSwitchCallType; - -/// 被叫显示昵称字段还是手机号字段,默认显示昵称 -@property(nonatomic, assign) BOOL calleeShowPhone; - -@end - -@interface NERtcCallUIConfig : NSObject - -/// 透传 NERtcCallKit 初始化配置,如果不需要UI组件内部初始化 NERtcCallKit 则不传此参数即可 -@property(nonatomic, strong) NERtcCallOptions *option; - -/// appkey -@property(nonatomic, strong) NSString *appKey; - -/// UI 配置 -@property(nonatomic, strong) NECallUIConfig *uiConfig; - -@end - -NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.h index 49f2ba70..60bc2ba4 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.h +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.h @@ -5,19 +5,21 @@ #ifndef NERtcCallUIKit_h #define NERtcCallUIKit_h -#import "NECallParam.h" +#import +#import "NECallUIKitConfig.h" #import "NECallViewController.h" #import "NECustomButton.h" #import "NEExpandButton.h" -#import "NERtcCallUIConfig.h" +#import "NEUICallParam.h" #import "NEVideoOperationView.h" #import "NEVideoView.h" #import "NetManager.h" -#import "SettingManager.h" #import "NEAudioCallingController.h" #import "NEAudioInCallController.h" +#import "NECallViewBaseController.h" #import "NECalledViewController.h" +#import "NERingFile.h" #import "NEVideoCallingController.h" #import "NEVideoInCallController.h" @@ -36,18 +38,54 @@ extern NSString *_Nonnull kCalledState; NS_ASSUME_NONNULL_BEGIN +@protocol NETranscodingDelegate + +- (void)renderFrame:(NERtcVideoFrame *)frame withLayer:(AVSampleBufferDisplayLayer *)layer; + +@end + +@protocol NECallUIKitDelegate + +/// 当有呼叫来到时候的回调,根据返回值决定内部是否返回,未实现此回调内部默认弹出被叫页面 +- (void)didCallComingWithInviteInfo:(NEInviteInfo *)inviteInfo + withCallParam:(NEUICallParam *)callParam + withCompletion:(void (^)(BOOL success))completion; + +@end + @interface NERtcCallUIKit : NSObject /// UI状态配置类,如果用户需要自定义某个状态的UI,需要继承通话状态类,通过对应key值覆盖对应Class @property(nonatomic, strong, readonly) NSMutableDictionary *uiConfigDic; +/// 自定义UI,UI完全自己重写,呼叫组件只负责拉起此页面,此参数的优先级高于 uiConfigDic 配置, +/// 传入的类型要继承自 NECallViewBaseController 类 +@property(nonatomic, strong, nullable) Class customControllerClass; + +/// 铃声文件配置,默认初始化内部资源路径,如果需要替换再初始化之后修改对应路径,如果想禁止铃声播放,对应路径置空即可 +@property(nonatomic, strong) NERingFile *ringFile; + +/// UI Kit 代理回调 +@property(nonatomic, weak) id delegate; + + (instancetype)sharedInstance; /// 初始化,所有功能需要先初始化 /// @param config 初始化参数 -- (void)setupWithConfig:(NERtcCallUIConfig *)config; +- (void)setupWithConfig:(NECallUIKitConfig *)config; + +/// 主叫发起呼叫接口 +/// @param callParam 呼叫参数 +- (void)callWithParam:(NEUICallParam *)callParam; + +/// 设置自定义UI类 +- (void)setCustomCallClass:(NSMutableDictionary *)customDic; + +/// 转为小窗模式 +- (void)changeSmallModeWithTyple:(NECallType)callType; -- (void)callWithParam:(NECallParam *)callParam withCallType:(NERtcCallType)callType; +/// 回复为非小窗模式 +- (void)restoreNormalMode; /// 版本号 + (NSString *)version; diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.m index 8d459a99..c4901e82 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/NERtcCallUIKit.m @@ -3,9 +3,14 @@ // found in the LICENSE file. #import "NERtcCallUIKit.h" +#import #import #import -#import +#import +#import +#import +#import "NEBufferDisplayView.h" +#import "NECallKitUtil.h" #import "NetManager.h" NSString *kAudioCalling = @"kAudioCalling"; @@ -20,16 +25,60 @@ NSString *kMouldName = @"NERtcCallUIKit"; -@interface NERtcCallUIKit () +NSString *kCallStatusResult = @"result"; -@property(nonatomic, strong) NERtcCallUIConfig *config; +NSString *kCallStatusQueryKey = @"imkit://call/state/isIdle"; + +NSString *kCallStatusCallBackKey = @"imkit://call/state/result"; + +@interface NERtcCallUIKit () + +@property(nonatomic, strong) NECallUIKitConfig *config; @property(nonatomic, strong) UIWindow *keywindow; +@property(nonatomic, weak) UIWindow *preiousKeywindow; + @property(nonatomic, strong, readwrite) NSMutableDictionary *uiConfigDic; @property(nonatomic, strong) NSBundle *bundle; +@property(nonatomic, assign) CGRect originFrame; + +@property(nonatomic, strong) UIView *parentView; + +@property(nonatomic, strong) NECallViewBaseController *callViewController; + +@property(nonatomic, strong) AVPictureInPictureController *pipController; + +@property(nonatomic, strong) NEBufferDisplayView *displayView; + +/// 视频小窗大小 +@property(nonatomic, assign) CGSize smallVideoSize; + +/// 音频小窗大小 +@property(nonatomic, assign) CGSize smallAudioSize; + +/// 转码协议 +@property(nonatomic, strong) id transcodingDelegate; + +@property(nonatomic, weak) NERtcVideoCanvas *canvas; + +@property(nonatomic, strong) UIView *maskView; + +@property(nonatomic, strong) UIImageView *remoteHeaderImageView; + +@property(nonatomic, strong) NSString *currentRemoteAccid; + +@property(nonatomic, assign) BOOL isCalling; + +@property(nonatomic, assign) BOOL isCalled; + @end @implementation NERtcCallUIKit @@ -55,19 +104,28 @@ - (NSString *)appKey { return self.config.appKey; } -- (void)setupWithConfig:(NERtcCallUIConfig *)config { - if (nil != config.option && config.appKey != nil) { - [[NERtcCallKit sharedInstance] setupAppKey:config.appKey options:config.option]; +- (void)setupWithConfig:(NECallUIKitConfig *)config { + if (nil != config.config) { + [[NECallEngine sharedInstance] setup:config.config]; } [[XKit instance] registerService:self]; self.config = config; + + NSString *className = @"NETranscodingEngine"; + Class class = NSClassFromString(className); + if (class) { + id instance = [[class alloc] init]; + if ([instance conformsToProtocol:@protocol(NETranscodingDelegate)]) { + self.transcodingDelegate = instance; + } + } } - (instancetype)init { self = [super init]; if (self) { [NetManager shareInstance]; - [[NERtcCallKit sharedInstance] addDelegate:self]; + [[NECallEngine sharedInstance] addCallDelegate:self]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didDismiss:) name:kCallKitDismissNoti @@ -84,7 +142,21 @@ - (instancetype)init { object.callStatus = NIMRtcCallStatusCanceled; } }; - self.bundle = [NSBundle bundleForClass:self.class]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(appDidEnterBackground) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(appDidEnterForeground) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + self.bundle = [NSBundle bundleForClass:NERtcCallUIKit.class]; + self.ringFile = [[NERingFile alloc] initWithBundle:self.bundle]; + self.smallVideoSize = CGSizeMake(90, 160); + self.smallAudioSize = CGSizeMake(70, 70); } return self; } @@ -98,32 +170,68 @@ - (void)registerRouter { closure:^(NSDictionary *_Nonnull param) { if ([[NetManager shareInstance] isClose] == YES) { [UIApplication.sharedApplication.keyWindow - makeToast:[self localizableWithKey:@"network_error"]]; + ne_makeToast:[self localizableWithKey:@"network_error"]]; return; } - NECallParam *callParam = [[NECallParam alloc] init]; + NEUICallParam *callParam = [[NEUICallParam alloc] init]; callParam.currentUserAccid = [param objectForKey:@"currentUserAccid"]; callParam.remoteUserAccid = [param objectForKey:@"remoteUserAccid"]; callParam.remoteShowName = [param objectForKey:@"remoteShowName"]; callParam.remoteAvatar = [param objectForKey:@"remoteAvatar"]; + NSNumber *type = [param objectForKey:@"type"]; - NERtcCallType callType = NERtcCallTypeAudio; + NECallType callType = NECallTypeAudio; if (type.intValue == 1) { - callType = NERtcCallTypeAudio; + callType = NECallTypeAudio; } else if (type.intValue == 2) { - callType = NERtcCallTypeVideo; + callType = NECallTypeVideo; } - [self callWithParam:callParam withCallType:callType]; + callParam.callType = callType; + [self callWithParam:callParam]; }]; + + [[Router shared] + register:kCallStatusQueryKey + closure:^(NSDictionary *_Nonnull params) { + BOOL result = NECallEngine.sharedInstance.callStatus == NECallStatusIdle ? true : false; + [[Router shared] + use:kCallStatusCallBackKey + parameters:@{kCallStatusResult : [NSNumber numberWithBool:result]} + closure:^(id _Nullable obj, enum RouterState state, NSString *_Nonnull string){ + + }]; + }]; } -- (void)callWithParam:(NECallParam *)callParam withCallType:(NERtcCallType)callType { +- (void)setCustomCallClass:(NSMutableDictionary *)customDic { + for (NSString *key in customDic.allKeys) { + Class cls = customDic[key]; + [self.uiConfigDic setObject:cls forKey:key]; + } +} + +- (void)callWithParam:(NEUICallParam *)callParam { + YXAlogInfo(@"call uikit callWithParam called : %d", self.isCalled); + if (self.isCalled == YES) { + return; + } + self.isCalling = YES; NECallViewController *callVC = [[NECallViewController alloc] init]; if (callParam.remoteShowName.length <= 0) { callParam.remoteShowName = callParam.remoteUserAccid; } - callVC.isCaller = YES; - callVC.callType = callType; + callParam.enableAudioToVideo = self.config.uiConfig.enableAudioToVideo; + callParam.enableVideoToAudio = self.config.uiConfig.enableVideoToAudio; + callParam.useEnableLocalMute = self.config.uiConfig.useEnableLocalMute; + callParam.enableVirtualBackground = self.config.uiConfig.enableVirtualBackground; + callParam.enableCalleePreview = self.config.uiConfig.enableCalleePreview; + callParam.enableFloatingWindow = self.config.uiConfig.enableFloatingWindow; + callParam.enableFloatingWindowOutOfApp = self.config.uiConfig.enableFloatingWindowOutOfApp; + callParam.isCaller = YES; + if (self.customControllerClass != nil) { + [self showCustomClassController:callParam]; + return; + } callVC.status = NERtcCallStatusCalling; callVC.callParam = callParam; callVC.uiConfigDic = self.uiConfigDic; @@ -131,101 +239,544 @@ - (void)callWithParam:(NECallParam *)callParam withCallType:(NERtcCallType)callT [self showCallView:callVC]; } -- (void)onInvited:(NSString *)invitor - userIDs:(NSArray *)userIDs - isFromGroup:(BOOL)isFromGroup - groupID:(NSString *)groupID - type:(NERtcCallType)type - attachment:(NSString *)attachment { +- (void)onCallEnd:(NECallEndInfo *)info { + YXAlogInfo(@"call ui kit oncallend"); + [self stopPip]; +} + +- (UIImageView *)getRemoteHeaderImage { + UIImageView *remoteHeaderImage = [[UIImageView alloc] init]; + remoteHeaderImage.translatesAutoresizingMaskIntoConstraints = NO; + remoteHeaderImage.contentMode = UIViewContentModeScaleAspectFit; + remoteHeaderImage.clipsToBounds = YES; + remoteHeaderImage.layer.cornerRadius = 4.0; + return remoteHeaderImage; +} + +// 设置应用外小窗远端关闭视频时候的占位视图 +- (void)setRemoteWithUrl:(NSString *)url withAccid:(NSString *)accid { + YXAlogInfo(@"set url %@ set accid %@", url, accid); + [self.maskView removeFromSuperview]; + [self.remoteHeaderImageView removeFromSuperview]; + self.maskView = [self getMaskView]; + self.currentRemoteAccid = accid; + self.remoteHeaderImageView = [self getRemoteHeaderImage]; + [self.remoteHeaderImageView sd_setImageWithURL:[NSURL URLWithString:url] + placeholderImage:[UIImage imageNamed:@"avator" + inBundle:self.bundle + compatibleWithTraitCollection:nil]]; + [self.maskView addSubview:self.remoteHeaderImageView]; + [NSLayoutConstraint activateConstraints:@[ + [self.remoteHeaderImageView.centerXAnchor constraintEqualToAnchor:self.maskView.centerXAnchor], + [self.remoteHeaderImageView.centerYAnchor constraintEqualToAnchor:self.maskView.centerYAnchor], + [self.remoteHeaderImageView.widthAnchor constraintEqualToAnchor:self.maskView.widthAnchor + multiplier:0.5], + [self.remoteHeaderImageView.heightAnchor constraintEqualToAnchor:self.maskView.widthAnchor + multiplier:0.5] + ]]; +} + +- (void)onCallTypeChange:(NECallTypeChangeInfo *)info { + NSLog(@"onCallTypeChange value :%lu :%lu", (unsigned long)info.state, + (unsigned long)info.callType); + if (info.state == NECallSwitchStateAgree) { + if (info.callType == NECallTypeAudio) { + [self stopPip]; + } else { + [self createPipController]; + } + } +} + +- (void)onCallConnected:(NECallInfo *)info { + if (info.callType == NECallTypeVideo) { + [self createPipController]; + } +} + +- (void)onReceiveInvited:(NEInviteInfo *)info { if (self.config.uiConfig.disableShowCalleeView == YES) { return; } + YXAlogInfo(@"call uikit onReceiveInvited calling : %d", self.isCalling); + if (self.isCalling == YES) { + NEHangupParam *param = [[NEHangupParam alloc] init]; + [param setValue:[NSNumber numberWithInteger:TerminalCodeBusy] forKey:@"reasonCode"]; + [NECallEngine.sharedInstance hangup:param + completion:^(NSError *_Nullable error){ + }]; + return; + } + self.isCalled = YES; [NIMSDK.sharedSDK.userManager - fetchUserInfos:@[ invitor ] + fetchUserInfos:@[ info.callerAccId ] completion:^(NSArray *_Nullable users, NSError *_Nullable error) { if (error) { - [UIApplication.sharedApplication.keyWindow makeToast:error.description]; + [UIApplication.sharedApplication.keyWindow ne_makeToast:error.description]; return; } else { NIMUser *imUser = users.firstObject; - NECallViewController *callVC = [[NECallViewController alloc] init]; - NECallParam *callParam = [[NECallParam alloc] init]; + NEUICallParam *callParam = [[NEUICallParam alloc] init]; callParam.remoteUserAccid = imUser.userId; callParam.remoteShowName = self.config.uiConfig.calleeShowPhone == YES ? imUser.userInfo.mobile : imUser.userInfo.nickName; callParam.remoteAvatar = imUser.userInfo.avatarUrl; callParam.currentUserAccid = NIMSDK.sharedSDK.loginManager.currentAccount; + callParam.enableAudioToVideo = self.config.uiConfig.enableAudioToVideo; + callParam.enableVideoToAudio = self.config.uiConfig.enableVideoToAudio; + callParam.enableVirtualBackground = self.config.uiConfig.enableVirtualBackground; + callParam.enableCalleePreview = self.config.uiConfig.enableCalleePreview; + callParam.enableFloatingWindow = self.config.uiConfig.enableFloatingWindow; + callParam.enableFloatingWindowOutOfApp = + self.config.uiConfig.enableFloatingWindowOutOfApp; + callParam.callType = info.callType; + callParam.isCaller = NO; + if (self.customControllerClass != nil) { + if (self.delegate != nil && + [self.delegate respondsToSelector:@selector + (didCallComingWithInviteInfo:withCallParam:withCompletion:)]) { + [self.delegate didCallComingWithInviteInfo:info + withCallParam:callParam + withCompletion:^(BOOL success) { + if (success) { + [self showCustomClassController:callParam]; + } + }]; + return; + } + [self showCustomClassController:callParam]; + return; + } + NECallViewController *callVC = [[NECallViewController alloc] init]; callVC.callParam = callParam; - callVC.isCaller = NO; callVC.status = NERtcCallStatusCalled; - callVC.callType = type; callVC.uiConfigDic = self.uiConfigDic; callVC.config = self.config.uiConfig; + if (self.delegate != nil && + [self.delegate respondsToSelector:@selector + (didCallComingWithInviteInfo:withCallParam:withCompletion:)]) { + [self.delegate didCallComingWithInviteInfo:info + withCallParam:callParam + withCompletion:^(BOOL success) { + if (success) { + [self showCustomClassController:callParam]; + } + }]; + return; + } [self showCallView:callVC]; } }]; } -- (void)showCalled:(NIMUser *)imUser - callType:(NERtcCallType)type - attachment:(NSString *)attachment { +- (void)showCalled:(NIMUser *)imUser callType:(NECallType)type attachment:(NSString *)attachment { + if (self.keywindow != nil) { + return; + } NECallViewController *callVC = [[NECallViewController alloc] init]; - NECallParam *callParam = [[NECallParam alloc] init]; + NEUICallParam *callParam = [[NEUICallParam alloc] init]; callParam.remoteUserAccid = imUser.userId; callParam.remoteShowName = imUser.userInfo.mobile; callParam.remoteAvatar = imUser.userInfo.avatarUrl; callParam.currentUserAccid = NIMSDK.sharedSDK.loginManager.currentAccount; + callParam.enableVideoToAudio = self.config.uiConfig.enableVideoToAudio; + callParam.enableAudioToVideo = self.config.uiConfig.enableAudioToVideo; + callParam.callType = type; + callParam.isCaller = NO; + if (self.customControllerClass != nil) { + [self showCustomClassController:callParam]; + return; + } callVC.callParam = callParam; - callVC.isCaller = NO; callVC.status = NERtcCallStatusCalled; - callVC.callType = type; callVC.uiConfigDic = self.uiConfigDic; callVC.config = self.config.uiConfig; [self showCallView:callVC]; } -- (void)showCallView:(UIViewController *)callVC { +- (void)showCallView:(NECallViewBaseController *)callVC { + if (self.config.uiConfig.enableFloatingWindowOutOfApp == YES) { + [self setRemoteWithUrl:callVC.callParam.remoteAvatar + withAccid:callVC.callParam.remoteUserAccid]; + } + callVC.createPipSEL = @selector(createPipController); + callVC.stopPipSEL = @selector(stopPip); UINavigationController *nav = [self getKeyWindowNav]; UINavigationController *callNav = [[UINavigationController alloc] initWithRootViewController:callVC]; callNav.modalPresentationStyle = UIModalPresentationFullScreen; [callNav.navigationBar setHidden:YES]; [nav presentViewController:callNav animated:YES completion:nil]; + YXAlogInfo(@"call uikit show call view caller : %d", callVC.callParam.isCaller); +} + +- (void)stopPip { + if (self.pipController != nil && [self.pipController isPictureInPictureActive]) { + [self.pipController stopPictureInPicture]; + } + self.pipController = nil; } - (UINavigationController *)getKeyWindowNav { - UIWindow *window = [[UIWindow alloc] init]; - window.frame = [[UIScreen mainScreen] bounds]; - window.windowLevel = UIWindowLevelStatusBar - 1; + YXAlogInfo(@"call uikit getKeyWindowNav"); + if (self.keywindow == nil) { + UIWindow *window = [[UIWindow alloc] init]; + if (@available(iOS 13.0, *)) { + for (UIWindowScene *scene in UIApplication.sharedApplication.connectedScenes.allObjects) { + if (scene.activationState == UISceneActivationStateForegroundActive) { + window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene]; + } + } + } + window.frame = [[UIScreen mainScreen] bounds]; + window.windowLevel = UIWindowLevelStatusBar - 1; + self.keywindow = window; + self.preiousKeywindow = UIApplication.sharedApplication.keyWindow; + YXAlogInfo(@"create new window %@", self.keywindow); + YXAlogInfo(@"self.preiousKeywindow %@", self.preiousKeywindow); + } + UIViewController *root = [[UIViewController alloc] init]; root.view.backgroundColor = [UIColor clearColor]; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:root]; nav.navigationBar.tintColor = [UIColor clearColor]; nav.view.backgroundColor = [UIColor clearColor]; [nav.navigationBar setHidden:YES]; - self.keywindow = window; - window.rootViewController = nav; - window.backgroundColor = [UIColor clearColor]; - [window makeKeyAndVisible]; + self.keywindow.rootViewController = nav; + self.keywindow.window.backgroundColor = [UIColor clearColor]; + [self.keywindow makeKeyAndVisible]; return nav; } - (void)didDismiss:(NSNotification *)noti { + YXAlogInfo(@"call uikit didDismiss caller : %d called : %d", self.isCalling, self.isCalled); UINavigationController *nav = (UINavigationController *)self.keywindow.rootViewController; __weak typeof(self) weakSelf = self; [nav dismissViewControllerAnimated:YES completion:^{ - __strong typeof(self) strongSelf = weakSelf; - NSLog(@"self window %@", strongSelf.keywindow); - [strongSelf.keywindow resignKeyWindow]; - strongSelf.keywindow = nil; + NSLog(@"self window %@", weakSelf.keywindow); + YXAlogInfo(@"call uikit didDismiss completion"); }]; + + [self.keywindow resignKeyWindow]; + self.keywindow = nil; + if (self.parentView != nil && self.callViewController.view != self.parentView) { + [self.callViewController.view removeFromSuperview]; + } + self.parentView = nil; + self.callViewController = nil; + [self.pipController stopPictureInPicture]; + self.pipController = nil; + self.isCalled = NO; + self.isCalling = NO; +} + +- (void)showCustomClassController:(NEUICallParam *)callParam { + NECallViewBaseController *callViewController = [[self.customControllerClass alloc] init]; + callViewController.callParam = callParam; + if ([callViewController isKindOfClass:[NECallViewController class]]) { + NECallViewController *callVC = (NECallViewController *)callViewController; + callVC.status = callParam.isCaller == YES ? NERtcCallStatusCalling : NERtcCallStatusCalled; + callVC.callParam = callParam; + callVC.uiConfigDic = self.uiConfigDic; + callVC.config = self.config.uiConfig; + } + [self showCallView:callViewController]; } +#pragma mark - Small Window + +- (void)tryOpenWindowOutApp { + // 处理应用程序进入后台的操作 + NERtcVideoCanvas *canvas = [[NERtcVideoCanvas alloc] init]; + canvas.renderMode = kNERtcVideoRenderScaleCropFill; + canvas.useExternalRender = YES; + canvas.externalVideoRender = self; + [NERtcEngine.sharedEngine + setupRemoteVideoCanvas:canvas + forUserID:[[NECallEngine sharedInstance] getCallInfo].calleeInfo.uid]; + if (![self.pipController isPictureInPictureActive]) { + NSLog(@"isPictureInPictureSupported"); + dispatch_async(dispatch_get_main_queue(), ^{ + [self.pipController startPictureInPicture]; + }); + } +} + +- (void)appDidEnterBackground { + NSLog(@"appDidEnterBackground"); + + if ([self checkoutOutOfAppWindownEnable] == NO) { + return; + } + [self tryOpenWindowOutApp]; +} + +- (void)appDidEnterForeground { + [self.pipController stopPictureInPicture]; + NECallEngine *engine = [NECallEngine sharedInstance]; + if (engine.callStatus == NECallStatusInCall && [engine getCallInfo].callType == NECallTypeVideo && + self.callViewController != nil) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[NECallEngine sharedInstance] setupRemoteView:self.callViewController.recoveryView]; + }); + } + if (self.pipController != nil && [self.pipController isPictureInPictureActive]) { + [self.pipController stopPictureInPicture]; + self.pipController = nil; + dispatch_async(dispatch_get_main_queue(), ^{ + [self createPipController]; + }); + } +} + +/// 转为小窗模式 +- (void)changeSmallModeWithTyple:(NECallType)callType { + [self.keywindow resignKeyWindow]; + self.keywindow.hidden = YES; + [self.preiousKeywindow makeKeyWindow]; + UINavigationController *nav = (UINavigationController *)self.keywindow.rootViewController; + UINavigationController *rootNav = (UINavigationController *)nav.presentedViewController; + UIViewController *rootViewController = rootNav.viewControllers.firstObject; + UIScreen *screen = UIScreen.mainScreen; + CGFloat width = screen.bounds.size.width; + CGFloat height = screen.bounds.size.height; + if (self.parentView == nil) { + if ([rootViewController isKindOfClass:NECallViewBaseController.class]) { + NECallViewBaseController *call = (NECallViewBaseController *)rootViewController; + self.callViewController = call; + self.originFrame = call.view.frame; + self.parentView = call.view.superview; + call.recoveryView.backgroundColor = [UIColor grayColor]; + if (callType == NECallTypeVideo) { + call.view.frame = CGRectMake(width - self.smallVideoSize.width - call.floatMargin, 54, + self.smallVideoSize.width, self.smallVideoSize.height); + } else { + call.view.frame = CGRectMake(width - self.smallAudioSize.width - call.floatMargin, 54, + self.smallAudioSize.width, self.smallAudioSize.height); + } + [UIApplication.sharedApplication.keyWindow addSubview:call.view]; + } + } else { + NECallViewBaseController *call = (NECallViewBaseController *)self.callViewController; + CGFloat centerX = call.view.frame.origin.x + call.view.frame.size.width / 2.0; + if (callType == NECallTypeVideo && + !CGSizeEqualToSize(call.view.bounds.size, self.smallVideoSize)) { + CGFloat x = centerX > width / 2.0 ? width - self.smallVideoSize.width - call.floatMargin + : call.floatMargin; + CGFloat y = call.view.frame.origin.y; + if (y + call.view.frame.size.height + self.smallVideoSize.height + call.floatMargin > + height) { + y = height - self.smallVideoSize.height - call.floatMargin; + } + call.view.frame = CGRectMake(x, y, self.smallVideoSize.width, self.smallVideoSize.height); + call.audioSmallView.hidden = YES; + call.recoveryView.hidden = NO; + call.view.layer.cornerRadius = 0; + call.recoveryView.backgroundColor = [UIColor grayColor]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NECallEngine sharedInstance] setupRemoteView:call.recoveryView]; + }); + } else if (callType == NECallTypeAudio && + !CGSizeEqualToSize(call.view.bounds.size, self.smallAudioSize)) { + CGFloat x = centerX > width / 2.0 ? width - self.smallAudioSize.width - call.floatMargin + : call.floatMargin; + call.view.frame = CGRectMake(x, call.view.frame.origin.y, self.smallAudioSize.width, + self.smallAudioSize.height); + call.audioSmallView.hidden = NO; + call.view.layer.cornerRadius = 6; + call.maskView.hidden = YES; + } + } +} + +- (void)onVideoMuted:(BOOL)muted userID:(NSString *)userId { + YXAlogInfo(@"callkit ui onVideoMuted current accid : %@ userid : %@ mute : %d mask view : %@", + self.currentRemoteAccid, userId, muted, self.maskView); + + if (self.currentRemoteAccid.length > 0 && [self.currentRemoteAccid isEqualToString:userId]) { + self.maskView.hidden = !muted; + } +} + +/// 恢复为非小窗模式 +- (void)restoreNormalMode { + [self.keywindow makeKeyWindow]; + self.keywindow.hidden = NO; + UINavigationController *nav = (UINavigationController *)self.keywindow.rootViewController; + UINavigationController *rootNav = (UINavigationController *)nav.presentedViewController; + UIViewController *rootViewController = rootNav.viewControllers.firstObject; + + if ([rootViewController isKindOfClass:NECallViewBaseController.class]) { + NECallViewController *call = (NECallViewController *)rootViewController; + call.view.frame = self.originFrame; + [self.parentView addSubview:call.view]; + } + self.parentView = nil; + self.callViewController = nil; +} + +- (UIView *)getMaskView { + UIView *maskView = [[UIView alloc] init]; + maskView.translatesAutoresizingMaskIntoConstraints = NO; + CAGradientLayer *gradientLayer = [CAGradientLayer layer]; + gradientLayer.colors = @[ + (__bridge id)[NECallKitUtil colorWithHexString:@"#232529"].CGColor, + (__bridge id)[NECallKitUtil colorWithHexString:@"#5E6471"].CGColor + ]; + gradientLayer.locations = @[ @0.0, @1.0 ]; + gradientLayer.startPoint = CGPointMake(0, 0); + gradientLayer.endPoint = CGPointMake(0, 1); + CGFloat width = 360; + CGSize size = CGSizeMake(width, width / 9 * 16); + gradientLayer.frame = CGRectMake(0, 0, size.width, size.height); + [maskView.layer addSublayer:gradientLayer]; + maskView.hidden = YES; + return maskView; +} + +- (void)createPipController { + if (self.config.uiConfig.enableFloatingWindow == NO) { + return; + } + + if (self.config.uiConfig.enableFloatingWindowOutOfApp == NO) { + return; + } + + if (!_pipController) { + if (![AVPictureInPictureController isPictureInPictureSupported]) { + return; + } + UIView *sourceView = nil; + if (self.preiousKeywindow != nil) { + sourceView = self.preiousKeywindow.rootViewController.view; + } else { + sourceView = UIApplication.sharedApplication.keyWindow.rootViewController.view; + } + if (@available(iOS 15.0, *)) { + AVPictureInPictureControllerContentSource *contentSource = + [[AVPictureInPictureControllerContentSource alloc] + initWithActiveVideoCallSourceView:sourceView + contentViewController:[self getVideoCallViewController]]; + _pipController = [[AVPictureInPictureController alloc] initWithContentSource:contentSource]; + _pipController.delegate = self; + + _pipController.canStartPictureInPictureAutomaticallyFromInline = NO; + [_pipController stopPictureInPicture]; + } + } +} + +- (AVPictureInPictureVideoCallViewController *)getVideoCallViewController { + AVPictureInPictureVideoCallViewController *videoCallViewController = + [[AVPictureInPictureVideoCallViewController alloc] init]; + CGFloat width = 180; + CGSize newSize = CGSizeMake(width, width / 9 * 16); + videoCallViewController.preferredContentSize = CGSizeMake(newSize.width, newSize.height); + + self.displayView = [self createDisplayView]; + [videoCallViewController.view addSubview:self.displayView]; + [NSLayoutConstraint activateConstraints:@[ + [self.displayView.topAnchor constraintEqualToAnchor:videoCallViewController.view.topAnchor], + [self.displayView.leadingAnchor + constraintEqualToAnchor:videoCallViewController.view.leadingAnchor], + [self.displayView.trailingAnchor + constraintEqualToAnchor:videoCallViewController.view.trailingAnchor], + [self.displayView.bottomAnchor + constraintEqualToAnchor:videoCallViewController.view.bottomAnchor] + ]]; + if (self.maskView != nil) { + [videoCallViewController.view addSubview:self.maskView]; + [NSLayoutConstraint activateConstraints:@[ + [self.maskView.topAnchor constraintEqualToAnchor:videoCallViewController.view.topAnchor], + [self.maskView.leadingAnchor + constraintEqualToAnchor:videoCallViewController.view.leadingAnchor], + [self.maskView.trailingAnchor + constraintEqualToAnchor:videoCallViewController.view.trailingAnchor], + [self.maskView.bottomAnchor constraintEqualToAnchor:videoCallViewController.view.bottomAnchor] + ]]; + } + return videoCallViewController; +} + +- (NEBufferDisplayView *)createDisplayView { + NEBufferDisplayView *displayView = [[NEBufferDisplayView alloc] initWithFrame:CGRectZero]; + displayView.translatesAutoresizingMaskIntoConstraints = NO; + return displayView; +} + +- (BOOL)checkoutOutOfAppWindownEnable { + if ([NECallEngine sharedInstance].callStatus != NECallStatusInCall) { + // 不在通话中,不需要处理进入后台逻辑 + NSLog(@"appDidEnterBackground call status : %lu", + (unsigned long)NECallEngine.sharedInstance.callStatus); + return NO; + } + + NECallType calltype = [[NECallEngine sharedInstance] getCallInfo].callType; + if (calltype != NECallTypeVideo) { + // 音频呼叫没有应用外小窗 + return NO; + } + + if (self.config.uiConfig.enableFloatingWindow == YES && + self.config.uiConfig.enableFloatingWindowOutOfApp == YES) { + return YES; + } + return NO; +} + +#pragma mark - Rtc Delegate + +- (void)onNERtcEngineRenderFrame:(NERtcVideoFrame *_Nonnull)frame { + if (self.transcodingDelegate != nil && self.pipController != nil && + [self.pipController isPictureInPictureActive]) { + [self.transcodingDelegate renderFrame:frame withLayer:self.displayView.getLayer]; + } +} + +#pragma mark - pip delegate + +- (void)pictureInPictureControllerDidStopPictureInPicture: + (AVPictureInPictureController *)pictureInPictureController { + NSLog(@"call ui kit pictureInPictureControllerDidStopPictureInPicture"); +} + +- (void)pictureInPictureControllerDidStartPictureInPicture: + (AVPictureInPictureController *)pictureInPictureController { + NSLog(@"call ui kit pictureInPictureControllerDidStartPictureInPicture"); +} + +- (void)pictureInPictureControllerWillStopPictureInPicture: + (AVPictureInPictureController *)pictureInPictureController { + NSLog(@"call ui kit pictureInPictureControllerWillStopPictureInPicture"); +} + +- (void)pictureInPictureControllerWillStartPictureInPicture: + (AVPictureInPictureController *)pictureInPictureController { + NSLog(@"call ui kit pictureInPictureControllerWillStartPictureInPicture"); +} + +- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController + failedToStartPictureInPictureWithError:(NSError *)error { + NSLog(@"call ui kit pictureInPictureController error : %@", error); +} + +- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController + restoreUserInterfaceForPictureInPictureStopWithCompletionHandler: + (void (^)(BOOL))completionHandler { + if (self.callViewController != nil) { + [self.callViewController changeToNormal]; + } +} + +#pragma mark - Version + + (NSString *)version { - return @"1.8.2"; + return @"2.2.0"; } @end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEBufferDisplayView.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEBufferDisplayView.h new file mode 100644 index 00000000..020df7e6 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEBufferDisplayView.h @@ -0,0 +1,16 @@ +//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NEBufferDisplayView : UIView + +- (AVSampleBufferDisplayLayer *)getLayer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEBufferDisplayView.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEBufferDisplayView.m new file mode 100644 index 00000000..90b207b1 --- /dev/null +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEBufferDisplayView.m @@ -0,0 +1,25 @@ +//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Use of this source code is governed by a MIT license that can be +// found in the LICENSE file. + +#import "NEBufferDisplayView.h" + +@implementation NEBufferDisplayView + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect { + // Drawing code +} +*/ + ++ (Class)layerClass { + return AVSampleBufferDisplayLayer.class; +} + +- (AVSampleBufferDisplayLayer *)getLayer { + return (AVSampleBufferDisplayLayer *)self.layer; +} + +@end diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.h b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.h index 8604c52f..ad8e9978 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.h +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.h @@ -7,11 +7,20 @@ NS_ASSUME_NONNULL_BEGIN @interface NEVideoOperationView : UIView +/// 麦克风 @property(strong, nonatomic) UIButton *microPhone; +/// 开启/关闭视频 @property(strong, nonatomic) UIButton *cameraBtn; +/// 挂断 @property(strong, nonatomic) UIButton *hangupBtn; +/// 开启/关闭静音 @property(strong, nonatomic) UIButton *speakerBtn; +/// 通话中音视频通话类型切换 @property(strong, nonatomic) UIButton *mediaBtn; +/// 虚化按钮 +@property(strong, nonatomic) UIButton *virtualBtn; +/// 是否支持虚化 +@property(assign, nonatomic) BOOL enableVirtualBackground; - (void)changeAudioStyle; - (void)changeVideoStyle; @@ -19,6 +28,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)setGroupStyle; +- (void)removeMediaBtn; + @end NS_ASSUME_NONNULL_END diff --git a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.m b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.m index 86562072..2758a230 100644 --- a/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.m +++ b/NERtcCallUIKit/NERtcCallUIKit/Classes/View/NEVideoOperationView.m @@ -16,7 +16,7 @@ @implementation NEVideoOperationView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { - self.bundle = [NSBundle bundleForClass:self.class]; + self.bundle = [NSBundle bundleForClass:NEVideoOperationView.class]; [self setupUI]; } return self; @@ -118,15 +118,40 @@ - (UIButton *)mediaBtn { return _mediaBtn; } +- (UIButton *)virtualBtn { + if (nil == _virtualBtn) { + _virtualBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_virtualBtn setImage:[UIImage imageNamed:@"virtual_background_off" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateNormal]; + [_virtualBtn setImage:[UIImage imageNamed:@"virtual_background_on" + inBundle:self.bundle + compatibleWithTraitCollection:nil] + forState:UIControlStateSelected]; + _virtualBtn.accessibilityIdentifier = @"virtual_btn"; + } + return _virtualBtn; +} + - (void)changeAudioStyle { [self.stack removeArrangedSubview:self.cameraBtn]; [self.cameraBtn removeFromSuperview]; self.mediaBtn.selected = YES; + if (self.enableVirtualBackground == YES) { + [self.stack removeArrangedSubview:self.virtualBtn]; + } + self.virtualBtn.hidden = YES; } - (void)changeVideoStyle { [self.stack insertArrangedSubview:self.cameraBtn atIndex:1]; self.mediaBtn.selected = NO; + if (self.enableVirtualBackground == YES) { + [self.stack insertArrangedSubview:self.virtualBtn atIndex:4]; + self.virtualBtn.selected = NO; + self.virtualBtn.hidden = NO; + } } - (void)hideMediaSwitch { @@ -143,4 +168,16 @@ - (void)setGroupStyle { [self.speakerBtn removeFromSuperview]; } +- (void)removeMediaBtn { + [self.stack removeArrangedSubview:self.mediaBtn]; + [self.mediaBtn removeFromSuperview]; +} + +- (void)setEnableVirtualBackground:(BOOL)enableVirtualBackground { + _enableVirtualBackground = enableVirtualBackground; + if (enableVirtualBackground == YES) { + [self.stack insertArrangedSubview:self.virtualBtn atIndex:4]; + } +} + @end diff --git a/NETeamUIKit/NETeamUIKit.podspec b/NETeamUIKit/NETeamUIKit.podspec index a0b89457..2e0cdd69 100644 --- a/NETeamUIKit/NETeamUIKit.podspec +++ b/NETeamUIKit/NETeamUIKit.podspec @@ -37,7 +37,6 @@ TODO: Add long description of the pod here. s.source_files = 'NETeamUIKit/Classes/**/*' s.resource = 'NETeamUIKit/Assets/**/*' s.dependency 'NECommonUIKit' - s.dependency 'NECommonKit' s.dependency 'NEChatKit' end diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunHistoryMessageCell.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunHistoryMessageCell.swift index b63ff224..254ed1b6 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunHistoryMessageCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunHistoryMessageCell.swift @@ -1,9 +1,9 @@ +import NIMSDK // Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. import UIKit -import NIMSDK @objcMembers open class FunHistoryMessageCell: NEBaseHistoryMessageCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamDefaultIconCell.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamDefaultIconCell.swift index cb55a47e..f87e0eb5 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamDefaultIconCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamDefaultIconCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit +import UIKit @objcMembers open class FunTeamDefaultIconCell: NEBaseTeamDefaultIconCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamMemberCell.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamMemberCell.swift index 49732ccc..557fce04 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamMemberCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamMemberCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamSettingHeaderCell.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamSettingHeaderCell.swift index 3c72007a..feeee974 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamSettingHeaderCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamSettingHeaderCell.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit +import UIKit @objcMembers open class FunTeamSettingHeaderCell: NEBaseTeamSettingHeaderCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamUserCell.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamUserCell.swift index 596b0506..d692aac4 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamUserCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Cell/FunTeamUserCell.swift @@ -2,11 +2,11 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit -import NIMSDK import NECoreIMKit import NECoreKit +import NIMSDK +import UIKit @objcMembers open class FunTeamUserCell: NEBaseTeamUserCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamAvatarViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamAvatarViewController.swift index 9d05ba32..ef878fd2 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamAvatarViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamAvatarViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NIMSDK +import UIKit @objcMembers open class FunTeamAvatarViewController: NEBaseTeamAvatarViewController { @@ -21,8 +21,8 @@ open class FunTeamAvatarViewController: NEBaseTeamAvatarViewController { super.setupUI() headerView.layer.cornerRadius = 6.4 - addRightAction(localizable("save"), #selector(savePhoto), self, .funTeamThemeColor) navigationController?.navigationBar.backgroundColor = .white + addRightAction(localizable("save"), #selector(savePhoto), self, .funTeamThemeColor) customNavigationView.backgroundColor = .white customNavigationView.moreButton.setTitleColor(.funTeamThemeColor, for: .normal) diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamHistoryMessageController.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamHistoryMessageController.swift index 47dc718c..be51019a 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamHistoryMessageController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamHistoryMessageController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunTeamHistoryMessageController: NEBaseTeamHistoryMessageController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamInfoViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamInfoViewController.swift index 902aa66d..d8452e3d 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamInfoViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamInfoViewController.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class FunTeamInfoViewController: NEBaseTeamInfoViewController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamIntroduceViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamIntroduceViewController.swift index 16a556bf..095047d5 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamIntroduceViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamIntroduceViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class FunTeamIntroduceViewController: NEBaseTeamIntroduceViewController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamMembersController.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamMembersController.swift index 7e4ad1a8..9723510b 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamMembersController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamMembersController.swift @@ -1,9 +1,9 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit +import UIKit open class FunTeamMembersController: NEBaseTeamMembersController { let searchGrayBackView: UIView = { let view = UIView() diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamNameViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamNameViewController.swift index 8b0b3d65..7c0b435d 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamNameViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamNameViewController.swift @@ -2,9 +2,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK import NECommonKit +import NIMSDK +import UIKit @objcMembers open class FunTeamNameViewController: NEBaseTeamNameViewController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamSettingViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamSettingViewController.swift index 26c9e00e..0430757a 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamSettingViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/Controller/FunTeamSettingViewController.swift @@ -2,10 +2,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NECoreIMKit import NIMSDK +import UIKit @objcMembers open class FunTeamSettingViewController: NEBaseTeamSettingViewController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/FunTeamRouter.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/FunTeamRouter.swift index 0f88fe97..f1e62df0 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/FunTeamRouter.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/FunTeamRouter.swift @@ -3,8 +3,8 @@ // found in the LICENSE file. import Foundation -import NECoreKit import NECoreIMKit +import NECoreKit import NIMSDK public extension TeamRouter { diff --git a/NETeamUIKit/NETeamUIKit/Classes/FunUI/FunTeamUIColor.swift b/NETeamUIKit/NETeamUIKit/Classes/FunUI/FunTeamUIColor.swift index 64ca64df..365403d1 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/FunUI/FunTeamUIColor.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/FunUI/FunTeamUIColor.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NETeamUIKit/NETeamUIKit/Classes/NEBaseTeamRouter.swift b/NETeamUIKit/NETeamUIKit/Classes/NEBaseTeamRouter.swift index 3af68f83..112c400e 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NEBaseTeamRouter.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NEBaseTeamRouter.swift @@ -3,13 +3,13 @@ // found in the LICENSE file. import Foundation -import NECoreKit import NECoreIMKit +import NECoreKit import NIMSDK @objcMembers public class TeamRouter: NSObject { - public static let repo = TeamRepo() + public static let repo = TeamRepo.shared public static var iconUrls = ["https://s.netease.im/safe/ABg8YjWQWvcqO6sAAAAAAAAAAAA?_im_url=1", "https://s.netease.im/safe/ABg8YjmQWvcqO6sAAAAAAAABAAA?_im_url=1", "https://s.netease.im/safe/ABg8YjyQWvcqO6sAAAAAAAABAAA?_im_url=1", diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/HistoryMessageCell.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/HistoryMessageCell.swift index 2470b0cc..2c77cba5 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/HistoryMessageCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/HistoryMessageCell.swift @@ -1,9 +1,9 @@ +import NIMSDK // Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. import UIKit -import NIMSDK @objcMembers open class HistoryMessageCell: NEBaseHistoryMessageCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamDefaultIconCell.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamDefaultIconCell.swift index 0061fa4a..04e15474 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamDefaultIconCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamDefaultIconCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit +import UIKit @objcMembers open class TeamDefaultIconCell: NEBaseTeamDefaultIconCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamMemberCell.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamMemberCell.swift index 3405292b..0736b0c4 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamMemberCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamMemberCell.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamSettingHeaderCell.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamSettingHeaderCell.swift index 5298abc4..21dd5155 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamSettingHeaderCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamSettingHeaderCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit +import UIKit @objcMembers open class TeamSettingHeaderCell: NEBaseTeamSettingHeaderCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamUserCell.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamUserCell.swift index e3046fa1..28b23b25 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamUserCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Cell/TeamUserCell.swift @@ -3,11 +3,11 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit -import NIMSDK import NECoreIMKit import NECoreKit +import NIMSDK +import UIKit @objcMembers open class TeamUserCell: NEBaseTeamUserCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamAvatarViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamAvatarViewController.swift index c151f210..5c1e460a 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamAvatarViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamAvatarViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NIMSDK +import UIKit @objcMembers open class TeamAvatarViewController: NEBaseTeamAvatarViewController { @@ -80,7 +80,7 @@ open class TeamAvatarViewController: NEBaseTeamAvatarViewController { for: indexPath ) as? TeamDefaultIconCell { cell.iconImage.image = coreLoader.loadImage("icon_\(indexPath.row)") - + cell.iconImage.accessibilityIdentifier = "id.default\(indexPath.row + 1)" return cell } return UICollectionViewCell() diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamHistoryMessageController.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamHistoryMessageController.swift index 881b2e69..76fd186c 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamHistoryMessageController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamHistoryMessageController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class TeamHistoryMessageController: NEBaseTeamHistoryMessageController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamInfoViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamInfoViewController.swift index c664cd49..8ce04d94 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamInfoViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamInfoViewController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class TeamInfoViewController: NEBaseTeamInfoViewController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamIntroduceViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamIntroduceViewController.swift index 4ce17bf9..52d303a8 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamIntroduceViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamIntroduceViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class TeamIntroduceViewController: NEBaseTeamIntroduceViewController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamMembersController.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamMembersController.swift index 54ddd082..0640037a 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamMembersController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamMembersController.swift @@ -1,4 +1,4 @@ -//// Copyright (c) 2022 NetEase, Inc. All rights reserved. +// Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamNameViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamNameViewController.swift index 072b4140..8c0728b5 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamNameViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamNameViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK import NECommonKit +import NIMSDK +import UIKit @objcMembers open class TeamNameViewController: NEBaseTeamNameViewController { diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamSettingViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamSettingViewController.swift index a0ab6627..ed6f6327 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamSettingViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/Controller/TeamSettingViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NECoreIMKit import NIMSDK +import UIKit @objcMembers open class TeamSettingViewController: NEBaseTeamSettingViewController { @@ -123,6 +123,7 @@ open class TeamSettingViewController: NEBaseTeamSettingViewController { ]) let memberListBtn = UIButton() + memberListBtn.accessibilityIdentifier = "id.member" cornerView.addSubview(memberListBtn) memberListBtn.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ diff --git a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/NormalTeamRouter.swift b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/NormalTeamRouter.swift index 110cdaf0..fb5d3f14 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/NormalUI/NormalTeamRouter.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/NormalUI/NormalTeamRouter.swift @@ -3,8 +3,8 @@ // found in the LICENSE file. import Foundation -import NECoreKit import NECoreIMKit +import NECoreKit import NIMSDK public extension TeamRouter { diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/Model/SettingSectionModel.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/Model/SettingSectionModel.swift index b90d58c5..87eb5d52 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/Model/SettingSectionModel.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/Model/SettingSectionModel.swift @@ -9,4 +9,20 @@ import Foundation public class SettingSectionModel: NSObject { public var cellModels = [SettingCellModel]() override public init() {} + + // 设置圆角 + open func setCornerType() { + cellModels.forEach { model in + if model == cellModels.first { + model.cornerType = .topLeft.union(.topRight) + if model == cellModels.last { + model.cornerType = .topLeft.union(.topRight).union(.bottomLeft).union(.bottomRight) + } + } else if model == cellModels.last { + model.cornerType = .bottomLeft.union(.bottomRight) + } else { + model.cornerType = .none + } + } + } } diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/NEBaseTeamHistoryMessageController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/NEBaseTeamHistoryMessageController.swift index df172b13..49214611 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/NEBaseTeamHistoryMessageController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/NEBaseTeamHistoryMessageController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class NEBaseTeamHistoryMessageController: NEBaseViewController, UITextFieldDelegate, @@ -82,6 +82,10 @@ open class NEBaseTeamHistoryMessageController: NEBaseViewController, UITextField textField.returnKeyType = .search textField.addTarget(self, action: #selector(searchTextFieldChange), for: .editingChanged) textField.delegate = self + if let clearButton = textField.value(forKey: "_clearButton") as? UIButton { + clearButton.accessibilityIdentifier = "id.clear" + } + textField.accessibilityIdentifier = "id.search" return textField }() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/NEBaseTeamMembersController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/NEBaseTeamMembersController.swift index 3d0383ae..e1505295 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/NEBaseTeamMembersController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/NEBaseTeamMembersController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECoreKit +import UIKit @objcMembers open class NEBaseTeamMembersController: NEBaseViewController, UITableViewDelegate, @@ -29,6 +29,10 @@ open class NEBaseTeamMembersController: NEBaseViewController, UITableViewDelegat field.textColor = .ne_greyText field.font = UIFont.systemFont(ofSize: 14.0) field.backgroundColor = UIColor.ne_backcolor + if let clearButton = field.value(forKey: "_clearButton") as? UIButton { + clearButton.accessibilityIdentifier = "id.clear" + } + field.accessibilityIdentifier = "id.search" return field }() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseHistoryMessageCell.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseHistoryMessageCell.swift index 4519b101..89f9416d 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseHistoryMessageCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseHistoryMessageCell.swift @@ -1,9 +1,9 @@ +import NIMSDK // Copyright (c) 2022 NetEase, Inc. All rights reserved. // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. import UIKit -import NIMSDK @objcMembers open class NEBaseHistoryMessageCell: UITableViewCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamAvatarViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamAvatarViewController.swift index ca9af7c3..49a432b1 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamAvatarViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamAvatarViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NIMSDK +import UIKit @objcMembers open class NEBaseTeamAvatarViewController: NEBaseViewController, UICollectionViewDelegate, @@ -13,7 +13,7 @@ open class NEBaseTeamAvatarViewController: NEBaseViewController, UICollectionVie public typealias SaveCompletion = () -> Void public var block: SaveCompletion? public var team: NIMTeam? - public let repo = TeamRepo() + public let repo = TeamRepo.shared public let headerBack = UIView() public let photoImage = UIImageView() @@ -26,6 +26,7 @@ open class NEBaseTeamAvatarViewController: NEBaseViewController, UICollectionVie header.translatesAutoresizingMaskIntoConstraints = false header.clipsToBounds = true header.isUserInteractionEnabled = true + header.accessibilityIdentifier = "id.icon" return header }() @@ -80,6 +81,7 @@ open class NEBaseTeamAvatarViewController: NEBaseViewController, UICollectionVie photoImage.translatesAutoresizingMaskIntoConstraints = false photoImage.image = coreLoader.loadImage("photo") + photoImage.accessibilityIdentifier = "id.camera" headerBack.addSubview(photoImage) let gesture = UITapGestureRecognizer() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamDefaultIconCell.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamDefaultIconCell.swift index 3aebf550..7f597c84 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamDefaultIconCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamDefaultIconCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit +import UIKit @objcMembers open class NEBaseTeamDefaultIconCell: UICollectionViewCell { diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamInfoViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamInfoViewController.swift index 3b75caa9..8ab1ccb8 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamInfoViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamInfoViewController.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NIMSDK +import UIKit @objcMembers open class NEBaseTeamInfoViewController: NEBaseViewController, UITableViewDelegate, diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamIntroduceViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamIntroduceViewController.swift index 81201dd7..bdef70e8 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamIntroduceViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamIntroduceViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit import NIMSDK +import UIKit @objcMembers open class NEBaseTeamIntroduceViewController: NEBaseViewController, UITextViewDelegate { @@ -15,7 +15,7 @@ open class NEBaseTeamIntroduceViewController: NEBaseViewController, UITextViewDe public var team: NIMTeam? public let textLimit = 100 - public let repo = TeamRepo() + public let repo = TeamRepo.shared public let backView = UIView() public lazy var textView: UITextView = { @@ -26,6 +26,7 @@ open class NEBaseTeamIntroduceViewController: NEBaseViewController, UITextViewDe text.delegate = self text.textContainerInset = UIEdgeInsets.zero text.layoutManager.allowsNonContiguousLayout = false + text.accessibilityIdentifier = "id.introduce" return text }() @@ -34,6 +35,7 @@ open class NEBaseTeamIntroduceViewController: NEBaseViewController, UITextViewDe text.translatesAutoresizingMaskIntoConstraints = false text.setImage(coreLoader.loadImage("clear_btn"), for: .normal) text.addTarget(self, action: #selector(clearText), for: .touchUpInside) + text.accessibilityIdentifier = "id.clear" return text }() @@ -42,6 +44,7 @@ open class NEBaseTeamIntroduceViewController: NEBaseViewController, UITextViewDe label.translatesAutoresizingMaskIntoConstraints = false label.textColor = NEConstant.hexRGB(0xB3B7BC) label.font = NEConstant.defaultTextFont(12.0) + label.accessibilityIdentifier = "id.flag" return label }() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamMemberCell.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamMemberCell.swift index 7a1a4194..733b2d03 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamMemberCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamMemberCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit +import UIKit @objcMembers open class NEBaseTeamMemberCell: UITableViewCell { @@ -15,6 +15,7 @@ open class NEBaseTeamMemberCell: UITableViewCell { header.layer.cornerRadius = 21 header.clipsToBounds = true header.translatesAutoresizingMaskIntoConstraints = false + header.accessibilityIdentifier = "id.avatar" return header }() @@ -30,6 +31,7 @@ open class NEBaseTeamMemberCell: UITableViewCell { label.layer.borderWidth = 1.0 label.text = localizable("team_owner") label.textAlignment = .center + label.accessibilityIdentifier = "id.identify" return label }() @@ -38,6 +40,7 @@ open class NEBaseTeamMemberCell: UITableViewCell { label.translatesAutoresizingMaskIntoConstraints = false label.font = NEConstant.defaultTextFont(16.0) label.textColor = .ne_darkText + label.accessibilityIdentifier = "id.userName" return label }() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamNameViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamNameViewController.swift index a8544e71..b30423c6 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamNameViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamNameViewController.swift @@ -3,9 +3,9 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit -import NIMSDK import NECommonKit +import NIMSDK +import UIKit @objcMembers open class NEBaseTeamNameViewController: NEBaseViewController, UITextViewDelegate { @@ -13,7 +13,7 @@ open class NEBaseTeamNameViewController: NEBaseViewController, UITextViewDelegat // var user: NIMUser? public var type = ChangeType.TeamName public var teamMember: NIMTeamMember? - public var repo = TeamRepo() + public var repo = TeamRepo.shared public let textLimit = 30 public let backView = UIView() @@ -24,6 +24,7 @@ open class NEBaseTeamNameViewController: NEBaseViewController, UITextViewDelegat label.textColor = NEConstant.hexRGB(0xB3B7BC) label.font = NEConstant.defaultTextFont(12.0) label.isUserInteractionEnabled = false + label.accessibilityIdentifier = "id.flag" return label }() @@ -33,6 +34,7 @@ open class NEBaseTeamNameViewController: NEBaseViewController, UITextViewDelegat text.textColor = NEConstant.hexRGB(0x333333) text.font = NEConstant.defaultTextFont(14.0) text.delegate = self + text.accessibilityIdentifier = "id.nickname" return text }() @@ -41,6 +43,7 @@ open class NEBaseTeamNameViewController: NEBaseViewController, UITextViewDelegat text.translatesAutoresizingMaskIntoConstraints = false text.setImage(coreLoader.loadImage("clear_btn"), for: .normal) text.addTarget(self, action: #selector(clearText), for: .touchUpInside) + text.accessibilityIdentifier = "id.clear" return text }() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingHeaderCell.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingHeaderCell.swift index 0bb20ad7..698da2d7 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingHeaderCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingHeaderCell.swift @@ -3,8 +3,8 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit +import UIKit @objcMembers open class NEBaseTeamSettingHeaderCell: NEBaseTeamSettingCell { @@ -12,6 +12,7 @@ open class NEBaseTeamSettingHeaderCell: NEBaseTeamSettingCell { let header = NEUserHeaderView(frame: .zero) header.translatesAutoresizingMaskIntoConstraints = false header.clipsToBounds = true + header.accessibilityIdentifier = "id.avatar" return header }() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingSelectCell.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingSelectCell.swift index aed0c9e2..a09f5922 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingSelectCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingSelectCell.swift @@ -12,6 +12,7 @@ open class NEBaseTeamSettingSelectCell: NEBaseTeamSettingCell { label.textColor = NEConstant.hexRGB(0x999999) label.font = NEConstant.defaultTextFont(14.0) label.translatesAutoresizingMaskIntoConstraints = false + label.accessibilityIdentifier = "id.subTitleValue" return label }() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingViewController.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingViewController.swift index fe1af1b4..28d4f912 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingViewController.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamSettingViewController.swift @@ -3,10 +3,10 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonUIKit import NECoreIMKit import NIMSDK +import UIKit @objcMembers open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionViewDelegate, @@ -51,6 +51,7 @@ open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionVi imageView.translatesAutoresizingMaskIntoConstraints = false imageView.clipsToBounds = true imageView.titleLabel.font = NEConstant.defaultTextFont(16.0) + imageView.accessibilityIdentifier = "id.avatar" return imageView }() @@ -59,6 +60,7 @@ open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionVi label.translatesAutoresizingMaskIntoConstraints = false label.font = NEConstant.defaultTextFont(16.0) label.textColor = NEConstant.hexRGB(0x333333) + label.accessibilityIdentifier = "id.name" return label }() @@ -67,6 +69,7 @@ open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionVi label.translatesAutoresizingMaskIntoConstraints = false label.font = NEConstant.defaultTextFont(16.0) label.textColor = NEConstant.hexRGB(0x999999) + label.accessibilityIdentifier = "id.count" return label }() @@ -87,6 +90,7 @@ open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionVi public lazy var addBtn: ExpandButton = { let button = ExpandButton() button.translatesAutoresizingMaskIntoConstraints = false + button.accessibilityIdentifier = "id.add" return button }() @@ -326,6 +330,17 @@ open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionVi for: indexPath ) as? NEBaseTeamSettingCell { cell.configure(model) + if let c = cell as? TeamSettingSwitchCell { + if model.cellName == localizable("message_remind") { + c.tSwitch.accessibilityIdentifier = "id.messageRemind" + } + if model.cellName == localizable("session_set_top") { + c.tSwitch.accessibilityIdentifier = "id.sessionPin" + } + if model.cellName == localizable("team_no_speak") { + c.tSwitch.accessibilityIdentifier = "id.teamMute" + } + } return cell } return UITableViewCell() @@ -571,6 +586,7 @@ open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionVi weakSelf?.updateInviteModeOwnerAction(model) } ownerActionButton.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") + ownerActionButton.accessibilityIdentifier = "id.teamOwner" actionSheetController.addAction(ownerActionButton) let allActionButton = UIAlertAction(title: localizable("team_all"), style: .default) { _ in @@ -578,6 +594,7 @@ open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionVi } allActionButton.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") + allActionButton.accessibilityIdentifier = "id.teamAllMember" actionSheetController.addAction(allActionButton) navigationController?.present(actionSheetController, animated: true, completion: nil) @@ -650,12 +667,14 @@ open class NEBaseTeamSettingViewController: NEBaseViewController, UICollectionVi weakSelf?.updateTeamInfoOwnerAction(model) } manager.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") + manager.accessibilityIdentifier = "id.teamOwner" actionSheetController.addAction(manager) let all = UIAlertAction(title: localizable("team_all"), style: .default) { _ in weakSelf?.updateTeamInfoAllAction(model) } all.setValue(UIColor.ne_darkText, forKey: "_titleTextColor") + all.accessibilityIdentifier = "id.teamAllMember" actionSheetController.addAction(all) navigationController?.present(actionSheetController, animated: true, completion: nil) diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamUserCell.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamUserCell.swift index 27d04fa8..f1855812 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamUserCell.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/View/NEBaseTeamUserCell.swift @@ -3,11 +3,11 @@ // Use of this source code is governed by a MIT license that can be // found in the LICENSE file. -import UIKit import NECommonKit -import NIMSDK import NECoreIMKit import NECoreKit +import NIMSDK +import UIKit @objcMembers open class NEBaseTeamUserCell: UICollectionViewCell { @@ -31,6 +31,7 @@ open class NEBaseTeamUserCell: UICollectionViewCell { header.translatesAutoresizingMaskIntoConstraints = false header.titleLabel.font = NEConstant.defaultTextFont(11.0) header.clipsToBounds = true + header.accessibilityIdentifier = "id.avatar" return header }() diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamInfoViewModel.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamInfoViewModel.swift index 1d40b38a..51d4acbe 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamInfoViewModel.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamInfoViewModel.swift @@ -3,8 +3,8 @@ // found in the LICENSE file. import Foundation -import NIMSDK import NECoreIMKit +import NIMSDK @objcMembers public class TeamInfoViewModel: NSObject { diff --git a/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamSettingViewModel.swift b/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamSettingViewModel.swift index 9cba9d16..2640692c 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamSettingViewModel.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/Setting/ViewModel/TeamSettingViewModel.swift @@ -3,9 +3,9 @@ // found in the LICENSE file. import Foundation +import NECoreIMKit import NIMSDK import UIKit -import NECoreIMKit protocol TeamSettingViewModelDelegate: NSObjectProtocol { func didClickChangeNick() @@ -25,7 +25,7 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { public var teamInfoModel: TeamInfoModel? - public let repo = TeamRepo() + public let repo = TeamRepo.shared public var memberInTeam: NIMTeamMember? @@ -73,14 +73,15 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { weak var weakSelf = self + // 标记 let mark = SettingCellModel() mark.cellName = localizable("mark") mark.type = SettingCellType.SettingArrowCell.rawValue - mark.cornerType = .topLeft.union(.topRight) mark.cellClick = { weakSelf?.delegate?.didClickMark() } + // 历史记录 let history = SettingCellModel() history.cellName = localizable("historical_record") history.type = SettingCellType.SettingArrowCell.rawValue @@ -88,6 +89,7 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { weakSelf?.delegate?.didClickHistoryMessage() } + // 开启消息提醒 let remind = SettingCellModel() remind.cellName = localizable("message_remind") remind.type = SettingCellType.SettingSwitchCell.rawValue @@ -121,10 +123,10 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { } } + // 聊天置顶 let setTop = SettingCellModel() setTop.cellName = localizable("session_set_top") setTop.type = SettingCellType.SettingSwitchCell.rawValue - setTop.cornerType = .bottomLeft.union(.bottomRight) if let tid = teamInfoModel?.team?.teamId { let session = NIMSession(tid, type: .team) @@ -161,8 +163,13 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { } } - model.cellModels.append(contentsOf: [mark, history, remind, setTop]) - + model.cellModels.append(contentsOf: [ + mark, // 标记 + history, // 历史记录 + remind, // 开启消息提醒 + setTop, // 聊天置顶 + ]) + model.setCornerType() return model } @@ -201,15 +208,11 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { } } + model.cellModels.append(nick) if isOwner() { - nick.cornerType = .topLeft.union(.topRight) - forbiddenWords.cornerType = .bottomLeft.union(.bottomRight) - model.cellModels.append(contentsOf: [nick, forbiddenWords]) - } else { - nick.cornerType = .topLeft.union(.topRight).union(.bottomLeft).union(.topRight) - model.cellModels.append(contentsOf: [nick]) + model.cellModels.append(forbiddenWords) } - + model.setCornerType() return model } @@ -233,12 +236,9 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { weakSelf?.delegate?.didChangeInviteModeClick(invitePermission) } - invitePermission.cornerType = .topLeft.union(.topRight) - let modifyPermission = SettingCellModel() modifyPermission.cellName = localizable("modify_team_info_permission") modifyPermission.type = SettingCellType.SettingSelectCell.rawValue - modifyPermission.cornerType = .bottomLeft.union(.bottomRight) modifyPermission.rowHeight = 73 if let updateMode = teamInfoModel?.team?.updateInfoMode, updateMode == .all { modifyPermission.subTitle = localizable("team_all") @@ -254,7 +254,6 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { let agreePermission = SettingCellModel() agreePermission.cellName = localizable("agree") agreePermission.type = SettingCellType.SettingSwitchCell.rawValue - agreePermission.cornerType = .bottomLeft.union(.bottomRight) if let inviteMode = teamInfoModel?.team?.beInviteMode, inviteMode == .needAuth { agreePermission.switchOpen = true } @@ -292,6 +291,7 @@ public class TeamSettingViewModel: NSObject, NIMTeamManagerDelegate { if isOwner() { model.cellModels.append(contentsOf: [invitePermission, modifyPermission]) + model.setCornerType() } return model diff --git a/NETeamUIKit/NETeamUIKit/Classes/TeamConstant.swift b/NETeamUIKit/NETeamUIKit/Classes/TeamConstant.swift index 3bcdcebd..0ca9ea84 100644 --- a/NETeamUIKit/NETeamUIKit/Classes/TeamConstant.swift +++ b/NETeamUIKit/NETeamUIKit/Classes/TeamConstant.swift @@ -4,11 +4,11 @@ // found in the LICENSE file. import Foundation -@_exported import NECoreKit -@_exported import NECommonUIKit -@_exported import NECommonKit @_exported import NEChatKit +@_exported import NECommonKit +@_exported import NECommonUIKit @_exported import NECoreIMKit +@_exported import NECoreKit let coreLoader = CoreLoader() func localizable(_ key: String) -> String { coreLoader.localizable(key) diff --git a/Podfile b/Podfile index 9700b56f..3efbd7be 100644 --- a/Podfile +++ b/Podfile @@ -10,56 +10,46 @@ target 'app' do pod 'YXLogin', '1.0.0' #可选UI库 - pod 'NEContactUIKit', '9.6.0' - pod 'NEConversationUIKit', '9.6.0' - pod 'NEChatUIKit', '9.6.0' - pod 'NETeamUIKit', '9.6.0' + # pod 'NEContactUIKit', '9.6.0' +# pod 'NEConversationUIKit', '9.6.0' + # pod 'NEChatUIKit', '9.6.0' +# pod 'NETeamUIKit', '9.6.0' # #可选Kit库(和UIKit对应) - pod 'NEChatKit', '9.6.0' +# pod 'NEChatKit', '9.6.0' # #基础kit库 - pod 'NECommonUIKit', '9.6.0' - pod 'NECommonKit', '9.6.0' - pod 'NECoreIMKit', '9.6.0' - pod 'NECoreKit', '9.6.0' +# pod 'NECommonUIKit', '9.6.0' +# pod 'NECommonKit', '9.6.0' +# pod 'NECoreIMKit', '9.6.0' +# pod 'NECoreKit', '9.6.0' # #扩展库 - pod 'NEMapKit', '9.6.0' + # pod 'NEMapKit', '9.6.0' #呼叫组件,音视频通话能力,需要开通 音视频2.0,可选,聊天一面会根据依赖初始化自动显示音视频通话入口 - pod 'NERtcCallUIKit', '1.8.2' - pod 'NERtcCallKit', '1.8.2' - pod 'NERtcSDK', '4.6.50' +# pod 'NERtcCallUIKit', '1.8.2' +# pod 'NERtcCallKit', '1.8.2' +# pod 'NERtcSDK', '4.6.50' # 如果需要查看UI部分源码请注释掉以上在线依赖,打开下面的本地依赖 -# pod 'NEContactUIKit', :path => 'NEContactUIKit/NEContactUIKit.podspec' -# pod 'NEConversationUIKit', :path => 'NEConversationUIKit/NEConversationUIKit.podspec' -# pod 'NETeamUIKit', :path => 'NETeamUIKit/NETeamUIKit.podspec' -# pod 'NEChatUIKit', :path => 'NEChatUIKit/NEChatUIKit.podspec' -# pod 'NEMapKit', :path => 'NEMapKit/NEMapKit.podspec' -# pod 'NERtcCallUIKit', :path => 'NERtcCallUIKit/NERtcCallUIKit.podspec' + pod 'NEContactUIKit', :path => 'NEContactUIKit/NEContactUIKit.podspec' + pod 'NEConversationUIKit', :path => 'NEConversationUIKit/NEConversationUIKit.podspec' + pod 'NETeamUIKit', :path => 'NETeamUIKit/NETeamUIKit.podspec' + pod 'NEChatUIKit', :path => 'NEChatUIKit/NEChatUIKit.podspec' + pod 'NEMapKit', :path => 'NEMapKit/NEMapKit.podspec' + pod 'NERtcCallUIKit', :path => 'NERtcCallUIKit/NERtcCallUIKit.podspec' end -#fix bug in Xcode 14 +#⚠️如果pod依赖报错,可打开以下注释 post_install do |installer| installer.pods_project.targets.each do |target| - if target.name == 'RSKPlaceholderTextView' - target.build_configurations.each do |config| - config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' - end + target.build_configurations.each do |config| + config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0' end end end - -#⚠️如果pod依赖报错,可打开以下注释 -#post_install do |installer| -# installer.pods_project.targets.each do |target| -# target.build_configurations.each do |config| -# config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' -# end -# end -#end diff --git a/app.xcodeproj/project.pbxproj b/app.xcodeproj/project.pbxproj index 7fbb2d71..5636a08c 100644 --- a/app.xcodeproj/project.pbxproj +++ b/app.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 53; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -655,7 +655,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 9.2.9; + MARKETING_VERSION = 9.6.3; PRODUCT_BUNDLE_IDENTIFIER = com.netease.yunxin.app.im; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -704,7 +704,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 9.2.9; + MARKETING_VERSION = 9.6.3; PRODUCT_BUNDLE_IDENTIFIER = com.netease.yunxin.app.im; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = inHouseYunxin; diff --git a/app/Main/AppDelegate.swift b/app/Main/AppDelegate.swift index 641ee855..551cabd9 100644 --- a/app/Main/AppDelegate.swift +++ b/app/Main/AppDelegate.swift @@ -39,8 +39,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD option.apnsCername = AppKey.pushCerName IMKitClient.instance.setupCoreKitIM(option) - let account = "<#account#>" - let token = "<#token#>" + let account = "338920520839424" + let token = "16a4518a-c66f-4ccb-b54d-2e8dd58dc8d2" weak var weakSelf = self IMKitClient.instance.loginIM(account, token) { error in @@ -145,8 +145,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD option.apnsCerName = AppKey.pushCerName option.isDisableLog = true option.supportAutoJoinWhenCalled = false - let uiConfig = NERtcCallUIConfig() - uiConfig.option = option + NERtcCallKit.sharedInstance().setupAppKey(AppKey.appKey, options: option) + let uiConfig = NECallUIKitConfig() uiConfig.appKey = AppKey.appKey uiConfig.uiConfig.showCallingSwitchCallType = option.supportAutoJoinWhenCalled NERtcCallKit.sharedInstance().timeOutSeconds = 30 diff --git a/app/Main/AppKey.swift b/app/Main/AppKey.swift index 234281af..618e0c4a 100644 --- a/app/Main/AppKey.swift +++ b/app/Main/AppKey.swift @@ -6,7 +6,7 @@ public struct AppKey { #if DEBUG public static let pushCerName = "<#请输入推送证书#>" - public static let appKey = "<#请输入appkey#>" + public static let appKey = "3e215d27b6a6a9e27dad7ef36dd5b65c" public static let gaodeMapAppkey = "<#输入高德地图key#>" #else public static let pushCerName = "<#请输入推送证书#>"