私聊完成

This commit is contained in:
fengshuo
2024-03-01 15:39:53 +08:00
parent 41ad01515d
commit 6b87cffe44
28 changed files with 4674 additions and 4126 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -7,7 +7,8 @@
import UIKit
import NIMSDK
class ChatVC: BaseViewController, HiddenNavigationBarProtocol {
import TZImagePickerController
class ChatVC: BaseViewController, HiddenNavigationBarProtocol, TZImagePickerControllerDelegate{
// /
private var isBecome: Bool = false
@@ -57,6 +58,8 @@ class ChatVC: BaseViewController, HiddenNavigationBarProtocol {
private func registerChatCell() {
chatTableView.register(cellType: ChatTextCell.self)
chatTableView.register(cellType: ChatTimeCell.self)
chatTableView.register(cellType: ChatVoiceCell.self)
chatTableView.register(cellType: ChatImageCell.self)
}
private lazy var chatTableView: UITableView = {
@@ -111,8 +114,20 @@ extension ChatVC: ChatKeyboardViewDelegate {
}
func keyboard(_ keyboard: ChatKeyboardView, DidMoreMenu type: ChatMoreMenuType) {
//TODO:
if type == .album {
let imagePicker = TZImagePickerController(maxImagesCount: 1, columnNumber: 5, delegate: self)
imagePicker?.allowPickingVideo = false
imagePicker?.modalPresentationStyle = .fullScreen
imagePicker?.didFinishPickingPhotosHandle = {(images: [UIImage]?, assets:[Any]?, isSelectOriginalPhoto: Bool) in
if (type == .album) {
if let image = images?[safe:0] {
self.vm.sendImageMessage(image: image) { _ in}
}
}
}
self.navigationController?.present(imagePicker!, animated: true)
keyboard.hiddenMoreView()
}
}
func keyboard(_ keyboard: ChatKeyboardView, DidObserver offsetY: CGFloat) {
@@ -123,6 +138,7 @@ extension ChatVC: ChatKeyboardViewDelegate {
extension ChatVC {
func requestInfo() {
self.navView.uid = vm.session.sessionId
let params = ["uid": vm.session.sessionId]
RequestGet(path: "user/get", parma: params) { data in
if let info = Deserialized<UserObject>.toModel(with: data) {
@@ -133,7 +149,7 @@ extension ChatVC {
}
let par:[String : Any] = ["uid": AuthManager.userUid, "isLikeUid": vm.session.sessionId]
RequestGet(path: "fans/isLike", parma: par) { data in
RequestGet(path: "fans/islike", parma: par) { data in
if let isLike = data as? Bool {
self.navView.isLike = isLike
}
@@ -194,6 +210,7 @@ extension ChatVC {
animated: false
)
}
chatTableView.reloadData()
}
public func tableViewDeleteIndexs(_ indexs: [IndexPath]) {
@@ -211,7 +228,7 @@ extension ChatVC {
}
extension ChatVC: ChatViewModelDelegate{
public func onRecvMessages(_ messages: [NIMMessage]) {
public func onRecvMessages1(_ messages: [NIMMessage]) {
insertRows()
vm.markRead(messages: messages) { error in
@@ -229,7 +246,9 @@ extension ChatVC: ChatViewModelDelegate{
public func send(_ message: NIMMessage, progress: Float) {}
public func send(_ message: NIMMessage, didCompleteWithError error: Error?) {
if error == nil {
insertRows()
}
}
private func indexPathsWithMessags(_ messages: [NIMMessage]) -> [IndexPath] {
@@ -263,10 +282,21 @@ extension ChatVC: UITableViewDelegate, UITableViewDataSource, UIScrollViewDelega
if model?.type == .text {
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ChatTextCell.self)
cell.model = model
return cell
} else if model?.type == .time {
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ChatTimeCell.self)
cell.model = model
return cell
} else if model?.type == .voice {
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ChatVoiceCell.self)
cell.model = model
return cell
} else if model?.type == .image {
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: ChatImageCell.self)
cell.model = model
return cell
}
return UITableViewCell()
}

View File

@@ -33,7 +33,8 @@ class ChatKeyboardView: UIView {
private let kLeft: CGFloat = 12.0
private let kSpace: CGFloat = 12.0
private let kViewWH: CGFloat = 26.0
private let kLineHeight: CGFloat = 0.75
private let kTextHeight: CGFloat = 36
// MARK: - var lazy
@@ -69,7 +70,7 @@ class ChatKeyboardView: UIView {
fileprivate lazy var changeButton : UIButton = {
let button = UIButton(type: .custom)
let x: CGFloat = self.kLeft
button.frame = CGRect(x: x, y: self.kSpace + 5, width: self.kViewWH, height: self.kViewWH)
button.frame = CGRect(x: x, y: self.kSpace + (kTextHeight - kViewWH) / 2.0, width: self.kViewWH, height: self.kViewWH)
button.setImage(UIImage(named: "chat_input_text"), for: .normal)
button.setImage(UIImage(named: "chat_voice"), for: .highlighted)
button.addTarget(self, action: #selector(changeDidAction(_:)), for: .touchUpInside)
@@ -80,7 +81,7 @@ class ChatKeyboardView: UIView {
fileprivate lazy var moreButton : UIButton = {
let button = UIButton(type: .custom)
let x: CGFloat = ScreenWidth - self.kViewWH - self.kSpace
button.frame = CGRect(x: x, y: self.kSpace + 5, width: self.kViewWH, height: self.kViewWH)
button.frame = CGRect(x: x, y: self.kSpace + (kTextHeight - kViewWH) / 2.0, width: self.kViewWH, height: self.kViewWH)
button.setImage(UIImage(named: "chat_more"), for: .normal)
button.setImage(UIImage(named: "chat_more"), for: .highlighted)
button.addTarget(self, action: #selector(moreDidAction(_:)), for: .touchUpInside)
@@ -90,7 +91,7 @@ class ChatKeyboardView: UIView {
///
fileprivate lazy var chatTextView: ChatGrowingTextView = {
let w: CGFloat = ScreenWidth - self.kViewWH * 2 - self.kSpace * 3 - self.kSpace
let textView = ChatGrowingTextView(frame: CGRect(x: self.kSpace + self.kLeft + self.kViewWH, y: self.kSpace, width: w, height: 36))
let textView = ChatGrowingTextView(frame: CGRect(x: self.kSpace + self.kLeft + self.kViewWH, y: self.kSpace, width: w, height: kTextHeight))
textView.placeholder = "请输入..."
textView.textColor = ThemeColor(hexStr: "#000000")
textView.maxNumberOfLines = 5
@@ -310,6 +311,7 @@ extension ChatKeyboardView {
keyboardHeight = endFrame.height
//
isShowKeyboard = false
contentHeight = 0
let option = userInfo["UIKeyboardAnimationCurveUserInfoKey"] as! Int
let changedY = ScreenHeight - self.toolBarHeight - self.contentHeight
@@ -413,6 +415,14 @@ extension ChatKeyboardView {
delegate?.keyboard(self, DidBecome: true)
}
func hiddenMoreView() {
contentView.isHidden = true
moreMenuView.isHidden = true
isShowMore = false
contentHeight = 0.0
restToolbarContentHeight()
}
///
func restToolbarContentHeight(_ isRest: Bool = false) {
var changedY = ScreenHeight - self.toolBarHeight - contentHeight
@@ -433,6 +443,8 @@ extension ChatKeyboardView {
self.layoutIfNeeded()
}
}
// MARK: -
@@ -446,7 +458,7 @@ extension ChatKeyboardView {
toolBarView.frame = CGRect(x: toolBarView.x, y: 0, width: toolBarView.width, height: toolBarHeight)
let spaceY = toolBarView.height - kSpace - kViewWH
chatTextView.frame = CGRect(x: chatTextView.x, y: chatTextView.x, width: chatTextView.width, height: textHeight)
chatTextView.frame = CGRect(x: chatTextView.x, y: chatTextView.y, width: chatTextView.width, height: textHeight)
moreButton.frame = CGRect(x: moreButton.x, y: spaceY, width: moreButton.width, height: moreButton.height)
contentView.frame = CGRect(x: contentView.x, y: toolBarView.maxY, width: contentView.width, height: contentHeight)

View File

@@ -112,10 +112,10 @@ class ChatVoiceObject: ChatBaseObject {
required init(msg: NIMMessage?) {
super.init(msg: msg)
type = .voice
let voiceHeight = 30.0
let voiceHeight = 40.0
if let content = msg?.messageObject as? NIMAudioObject {
let scale = 2*atan((Double(content.duration)/1000.0-1)/10.0)/M_PI;
let low = (ChatUIConfig.layout.contentMaxWidth - 180)
let scale = 2*atan((Double(content.duration)/1000.0-1)/9.0)/M_PI;
let low = (ChatUIConfig.layout.contentMaxWidth - 160)
let max = (ChatUIConfig.layout.contentMaxWidth - 100)
let width = (max - low) * scale + low
if let path = content.path {
@@ -125,7 +125,7 @@ class ChatVoiceObject: ChatBaseObject {
contentSize = CGSize(width: width, height: voiceHeight)
height = Float(voiceHeight + ChatUIConfig.layout.cellContentInsets.bottom + ChatUIConfig.layout.cellContentInsets.top)
} else {
let low = (ChatUIConfig.layout.contentMaxWidth - 180)
let low = (ChatUIConfig.layout.contentMaxWidth - 160)
contentSize = CGSize(width: low , height: voiceHeight)
height = Float(voiceHeight + ChatUIConfig.layout.cellContentInsets.bottom + ChatUIConfig.layout.cellContentInsets.top)
}

View File

@@ -25,13 +25,12 @@ public protocol ChatViewModelDelegate: NSObjectProtocol {
func send(_ message: NIMMessage, didCompleteWithError error: Error?)
func send(_ message: NIMMessage, progress: Float)
func onRecvMessages(_ messages: [NIMMessage])
func onRecvMessages1(_ messages: [NIMMessage])
func willSend(_ message: NIMMessage)
}
public class ChatViewModel: NSObject,
NIMConversationManagerDelegate, NIMSystemNotificationManagerDelegate {
public class ChatViewModel: NSObject, NIMChatManagerDelegate {
private var userInfo = [String: NIMUser]()
public let messagPageNum: UInt = 100
@@ -52,8 +51,6 @@ public class ChatViewModel: NSObject,
private func addMessageListener() {
NIMSDK.shared().chatManager.add(self)
NIMSDK.shared().conversationManager.add(self)
NIMSDK.shared().systemNotificationManager.add(self)
}
init(session: NIMSession) {
@@ -316,6 +313,67 @@ public class ChatViewModel: NSObject,
}
}
public func send(_ message: NIMMessage, didCompleteWithError error: Error?) {
for (i, msg) in messageObjects.enumerated() {
if message.messageId == msg.msg?.messageId {
messageObjects[i].msg = message
break
}
}
delegate?.send(message, didCompleteWithError: error)
}
//
public func onRecvMessages(_ messages: [NIMMessage]) {
for msg in messages {
if msg.session?.sessionId == session.sessionId {
if let model = modelTransformMessage(message: msg) {
newMsg = msg
addTimeMessage(msg)
self.messageObjects.append(model)
}
}
}
delegate?.onRecvMessages1(messages)
}
public func willSend(_ message: NIMMessage) {
if message.session?.sessionId != session.sessionId {
return
}
guard let model = modelTransformMessage(message: message) else { return }
if newMsg == nil {
newMsg = message
}
var isResend = false
for (i, msg) in messageObjects.enumerated() {
if message.messageId == msg.msg?.messageId {
messageObjects[i].msg = message
isResend = true
break
}
}
if !isResend {
addTimeMessage(message)
messageObjects.append(model)
}
delegate?.didAppend(message)
}
public func onReceive(_ notification: NIMCustomSystemNotification) {
}
public func send(_ message: NIMMessage, progress: Float) {
delegate?.send(message, progress: progress)
}
@discardableResult
public func resendMessage(message: NIMMessage) -> Error? {
@@ -600,66 +658,3 @@ public class ChatViewModel: NSObject,
}
}
extension ChatViewModel: NIMChatManagerDelegate {
// MARK: NIMChatManagerDelegate
public func send(_ message: NIMMessage, didCompleteWithError error: Error?) {
for (i, msg) in messageObjects.enumerated() {
if message.messageId == msg.msg?.messageId {
messageObjects[i].msg = message
break
}
}
delegate?.send(message, didCompleteWithError: error)
}
//
public func onRecvMessages(_ messages: [NIMMessage]) {
for msg in messages {
if msg.session?.sessionId == session.sessionId {
if let model = modelTransformMessage(message: msg) {
newMsg = msg
addTimeMessage(msg)
self.messageObjects.append(model)
}
}
}
delegate?.onRecvMessages(messages)
}
public func willSend(_ message: NIMMessage) {
if message.session?.sessionId != session.sessionId {
return
}
guard let model = modelTransformMessage(message: message) else { return }
if newMsg == nil {
newMsg = message
}
var isResend = false
for (i, msg) in messageObjects.enumerated() {
if message.messageId == msg.msg?.messageId {
messageObjects[i].msg = message
isResend = true
break
}
}
if !isResend {
addTimeMessage(message)
messageObjects.append(model)
}
delegate?.didAppend(message)
}
public func onReceive(_ notification: NIMCustomSystemNotification) {
}
public func send(_ message: NIMMessage, progress: Float) {
delegate?.send(message, progress: progress)
}
}

View File

@@ -55,7 +55,7 @@ class ChatBaseCell: UITableViewCell, Reusable{
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
backgroundColor = ThemeColor(hexStr: "#F8F8FB")
backgroundColor = .clear
contentView.addSubview(avatarImgView)
contentView.addSubview(bubbleView)
contentView.addSubview(activityIndicatorView)

View File

@@ -37,6 +37,11 @@ class ChatImageCell: ChatBaseCell {
return imageView
}()
override func layoutMessageCell() {
super.layoutMessageCell()
setupCellLayout()
}
}
extension ChatImageCell {

View File

@@ -8,6 +8,7 @@
import UIKit
class ChatNavView: BaseView {
var uid:String = ""
var isLike:Bool? {
didSet {
@@ -54,6 +55,7 @@ class ChatNavView: BaseView {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "chat_back"), for: .normal)
button.setImage(UIImage(named: "chat_back"), for: .selected)
button.addTarget(self, action: #selector(backClick), for: .touchUpInside)
return button
}()
@@ -82,10 +84,35 @@ class ChatNavView: BaseView {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "chat_opt"), for: .normal)
button.setImage(UIImage(named: "chat_opt"), for: .selected)
button.addTarget(self, action: #selector(optClick), for: .touchUpInside)
return button
}()
@objc func optClick() {
let alertController = UIAlertController(title: nil,
message: nil,
preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: "举报", style: .default, handler: { action in
HUDTool.show(with: "举报成功, 我们将尽快处理")
}))
alertController.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { action in
}))
YMRequestX.topViewController()?.present(alertController, animated: true, completion: nil)
}
@objc func likeClick() {
//TODO:
let params:[String: Any] = ["uid": AuthManager.userUid, "ticket": AuthManager.ticket, "type":"1", "likedUid": uid]
RequestPost(path: "fans/like", parma: params) { _ in
self.likeBtn.isHidden = true
} fail: { code, msg in
HUDTool.show(with: msg)
}
}
@objc func backClick() {
YMRequestX.topViewController()?.navigationController?.popViewController(animated: true)
}
}

View File

@@ -21,7 +21,7 @@ class ChatTimeCell: UITableViewCell, Reusable {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
backgroundColor = ThemeColor(hexStr: "#F8F8FB")
backgroundColor = .clear
contentView.addSubview(timeLb)
timeLb.snp.makeConstraints { make in
make.edges.equalTo(contentView)

View File

@@ -12,7 +12,7 @@ class ChatVoiceCell: ChatBaseCell, NIMMediaManagerDelegate {
override var model: ChatSessionProtocol? {
didSet {
if let model = model as? ChatVoiceObject {
timeLabel.text = "\(model.duartion / 1000)"
timeLabel.text = "\(model.duartion / 1000)s"
}
}
}
@@ -28,8 +28,8 @@ class ChatVoiceCell: ChatBaseCell, NIMMediaManagerDelegate {
let imageView = UIImageView()
imageView.isUserInteractionEnabled = true
let firstImage = UIImage(named:"chat_audio_playing_first")!
let second = UIImage(named:"chat_audio_playing_first")!
let third = UIImage(named:"chat_audio_playing_first")!
let second = UIImage(named:"chat_audio_playing_second")!
let third = UIImage(named:"chat_audio_playing_third")!
imageView.animationImages = [firstImage, second, third];
imageView.animationDuration = 1
imageView.animationRepeatCount = 100
@@ -42,6 +42,8 @@ class ChatVoiceCell: ChatBaseCell, NIMMediaManagerDelegate {
NIMSDK.shared().mediaManager.setNeedProximityMonitor(false)
NIMSDK.shared().mediaManager.add(self)
loadSubViews()
let tap = UITapGestureRecognizer(target: self, action: #selector(didTapBackRecognizer))
addGestureRecognizer(tap)
}
@@ -89,6 +91,10 @@ class ChatVoiceCell: ChatBaseCell, NIMMediaManagerDelegate {
}
}
override func layoutMessageCell() {
super.layoutMessageCell()
setupCellLayout()
}
}