|
@@ -12,233 +12,212 @@ import MapKit
|
|
|
// MARK: MessagesLayoutDelegate
|
|
|
|
|
|
extension TSChatViewController: MessagesLayoutDelegate {
|
|
|
- func cellTopLabelHeight(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGFloat {
|
|
|
- 18
|
|
|
- }
|
|
|
-
|
|
|
- func cellBottomLabelHeight(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGFloat {
|
|
|
- 17
|
|
|
- }
|
|
|
-
|
|
|
- func messageTopLabelHeight(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGFloat {
|
|
|
- 20
|
|
|
- }
|
|
|
-
|
|
|
- func messageBottomLabelHeight(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> CGFloat {
|
|
|
- 16
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- func textCellSizeCalculator(
|
|
|
- for _: MessageType,
|
|
|
- at _: IndexPath,
|
|
|
- in _: MessagesCollectionView)
|
|
|
- -> CellSizeCalculator?
|
|
|
- {
|
|
|
- self.textMessageSizeCalculator
|
|
|
- }
|
|
|
+ func customCellSizeCalculator(for message: any MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CellSizeCalculator {
|
|
|
+ self.textMessageSizeCalculator
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
// MARK: MessagesDisplayDelegate
|
|
|
|
|
|
extension TSChatViewController: MessagesDisplayDelegate {
|
|
|
- // MARK: - Text Messages
|
|
|
-
|
|
|
- func textColor(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UIColor {
|
|
|
- isFromCurrentSender(message: message) ? .white : .darkText
|
|
|
- }
|
|
|
-
|
|
|
- func detectorAttributes(for detector: DetectorType, and _: MessageType, at _: IndexPath) -> [NSAttributedString.Key: Any] {
|
|
|
- switch detector {
|
|
|
- case .hashtag, .mention: return [.foregroundColor: UIColor.blue]
|
|
|
- default: return MessageLabel.defaultAttributes
|
|
|
+ // MARK: - Text Messages
|
|
|
+
|
|
|
+ func textColor(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UIColor {
|
|
|
+ return UIColor.mainBg
|
|
|
+ // isFromCurrentSender(message: message) ? UIColor.mainBg : .white
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- func enabledDetectors(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> [DetectorType] {
|
|
|
- [.url, .address, .phoneNumber, .date, .transitInformation, .mention, .hashtag]
|
|
|
- }
|
|
|
-
|
|
|
- // MARK: - All Messages
|
|
|
-
|
|
|
- func backgroundColor(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UIColor {
|
|
|
- isFromCurrentSender(message: message) ? .themeColor : UIColor(red: 230 / 255, green: 230 / 255, blue: 230 / 255, alpha: 1)
|
|
|
- }
|
|
|
-
|
|
|
- func messageStyle(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> MessageStyle {
|
|
|
- let tail: MessageStyle.TailCorner = isFromCurrentSender(message: message) ? .bottomRight : .bottomLeft
|
|
|
- if let image = UIImage(named: "bobbly") {
|
|
|
- return .customImageTail(image, tail)
|
|
|
- } else {
|
|
|
- return .bubbleTail(tail, .curved)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func configureAvatarView(_ avatarView: AvatarView, for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) {
|
|
|
-// let avatar = SampleData.shared.getAvatarFor(sender: message.sender)
|
|
|
- //设置聊天头像
|
|
|
- avatarView.set(avatar: Avatar(image: UIImage(named: "App-Icon")))
|
|
|
- }
|
|
|
-
|
|
|
- func configureMediaMessageImageView(
|
|
|
- _ imageView: UIImageView,
|
|
|
- for message: MessageType,
|
|
|
- at _: IndexPath,
|
|
|
- in _: MessagesCollectionView)
|
|
|
- {
|
|
|
- if case MessageKind.photo(let media) = message.kind, let imageURL = media.url {
|
|
|
- imageView.kf.setImage(with: imageURL)
|
|
|
- } else {
|
|
|
- imageView.kf.cancelDownloadTask()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // MARK: - Location Messages
|
|
|
-
|
|
|
- func annotationViewForLocation(message _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> MKAnnotationView? {
|
|
|
- let annotationView = MKAnnotationView(annotation: nil, reuseIdentifier: nil)
|
|
|
- let pinImage = #imageLiteral(resourceName: "ic_map_marker")
|
|
|
- annotationView.image = pinImage
|
|
|
- annotationView.centerOffset = CGPoint(x: 0, y: -pinImage.size.height / 2)
|
|
|
- return annotationView
|
|
|
- }
|
|
|
-
|
|
|
- func animationBlockForLocation(
|
|
|
- message _: MessageType,
|
|
|
- at _: IndexPath,
|
|
|
- in _: MessagesCollectionView) -> ((UIImageView) -> Void)?
|
|
|
- {
|
|
|
- { view in
|
|
|
- view.layer.transform = CATransform3DMakeScale(2, 2, 2)
|
|
|
- UIView.animate(
|
|
|
- withDuration: 0.6,
|
|
|
- delay: 0,
|
|
|
- usingSpringWithDamping: 0.9,
|
|
|
- initialSpringVelocity: 0,
|
|
|
- options: [],
|
|
|
- animations: {
|
|
|
- view.layer.transform = CATransform3DIdentity
|
|
|
- },
|
|
|
- completion: nil)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func snapshotOptionsForLocation(
|
|
|
- message _: MessageType,
|
|
|
- at _: IndexPath,
|
|
|
- in _: MessagesCollectionView)
|
|
|
+
|
|
|
+ func detectorAttributes(for detector: DetectorType, and _: MessageType, at _: IndexPath) -> [NSAttributedString.Key: Any] {
|
|
|
+ switch detector {
|
|
|
+ case .hashtag, .mention: return [.foregroundColor: UIColor.blue]
|
|
|
+ default: return MessageLabel.defaultAttributes
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func enabledDetectors(for _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> [DetectorType] {
|
|
|
+ [.url, .address, .phoneNumber, .date, .transitInformation, .mention, .hashtag]
|
|
|
+ }
|
|
|
+
|
|
|
+ // MARK: - All Messages
|
|
|
+
|
|
|
+ func backgroundColor(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UIColor {
|
|
|
+ isFromCurrentSender(message: message) ? .themeColor : "#333333".uiColor
|
|
|
+ }
|
|
|
+
|
|
|
+ func messageStyle(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> MessageStyle {
|
|
|
+ let tail: MessageStyle.TailCorner = isFromCurrentSender(message: message) ? .bottomRight : .bottomLeft
|
|
|
+ if let image = UIImage(named: "bobbly") {
|
|
|
+ return .customImageTail(image, tail)
|
|
|
+ } else {
|
|
|
+ return .bubbleTail(tail, .curved)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func configureAvatarView(_ avatarView: AvatarView, for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) {
|
|
|
+ // let avatar = SampleData.shared.getAvatarFor(sender: message.sender)
|
|
|
+ //设置聊天头像
|
|
|
+ avatarView.set(avatar: Avatar(image: UIImage(named: "App-Icon")))
|
|
|
+ }
|
|
|
+
|
|
|
+ func configureMediaMessageImageView(
|
|
|
+ _ imageView: UIImageView,
|
|
|
+ for message: MessageType,
|
|
|
+ at _: IndexPath,
|
|
|
+ in _: MessagesCollectionView)
|
|
|
+ {
|
|
|
+ if case MessageKind.photo(let media) = message.kind, let imageURL = media.url {
|
|
|
+ imageView.kf.setImage(with: imageURL)
|
|
|
+ } else {
|
|
|
+ imageView.kf.cancelDownloadTask()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // MARK: - Location Messages
|
|
|
+
|
|
|
+ func annotationViewForLocation(message _: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> MKAnnotationView? {
|
|
|
+ let annotationView = MKAnnotationView(annotation: nil, reuseIdentifier: nil)
|
|
|
+ let pinImage = #imageLiteral(resourceName: "ic_map_marker")
|
|
|
+ annotationView.image = pinImage
|
|
|
+ annotationView.centerOffset = CGPoint(x: 0, y: -pinImage.size.height / 2)
|
|
|
+ return annotationView
|
|
|
+ }
|
|
|
+
|
|
|
+ func animationBlockForLocation(
|
|
|
+ message _: MessageType,
|
|
|
+ at _: IndexPath,
|
|
|
+ in _: MessagesCollectionView) -> ((UIImageView) -> Void)?
|
|
|
+ {
|
|
|
+ { view in
|
|
|
+ view.layer.transform = CATransform3DMakeScale(2, 2, 2)
|
|
|
+ UIView.animate(
|
|
|
+ withDuration: 0.6,
|
|
|
+ delay: 0,
|
|
|
+ usingSpringWithDamping: 0.9,
|
|
|
+ initialSpringVelocity: 0,
|
|
|
+ options: [],
|
|
|
+ animations: {
|
|
|
+ view.layer.transform = CATransform3DIdentity
|
|
|
+ },
|
|
|
+ completion: nil)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func snapshotOptionsForLocation(
|
|
|
+ message _: MessageType,
|
|
|
+ at _: IndexPath,
|
|
|
+ in _: MessagesCollectionView)
|
|
|
-> LocationMessageSnapshotOptions
|
|
|
- {
|
|
|
- LocationMessageSnapshotOptions(
|
|
|
- showsBuildings: true,
|
|
|
- showsPointsOfInterest: true,
|
|
|
- span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10))
|
|
|
- }
|
|
|
-
|
|
|
- // MARK: - Audio Messages
|
|
|
-
|
|
|
- func audioTintColor(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UIColor {
|
|
|
- isFromCurrentSender(message: message) ? .white : UIColor(red: 15 / 255, green: 135 / 255, blue: 255 / 255, alpha: 1.0)
|
|
|
- }
|
|
|
-
|
|
|
- func configureAudioCell(_ cell: AudioMessageCell, message: MessageType) {
|
|
|
-
|
|
|
- }
|
|
|
+ {
|
|
|
+ LocationMessageSnapshotOptions(
|
|
|
+ showsBuildings: true,
|
|
|
+ showsPointsOfInterest: true,
|
|
|
+ span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10))
|
|
|
+ }
|
|
|
+
|
|
|
+ // MARK: - Audio Messages
|
|
|
+
|
|
|
+ func audioTintColor(for message: MessageType, at _: IndexPath, in _: MessagesCollectionView) -> UIColor {
|
|
|
+ isFromCurrentSender(message: message) ? .white : UIColor(red: 15 / 255, green: 135 / 255, blue: 255 / 255, alpha: 1.0)
|
|
|
+ }
|
|
|
+
|
|
|
+ func configureAudioCell(_ cell: AudioMessageCell, message: MessageType) {
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
// MARK: MessageCellDelegate
|
|
|
|
|
|
extension TSChatViewController: MessageCellDelegate {
|
|
|
- func didTapAvatar(in _: MessageCollectionViewCell) {
|
|
|
- print("Avatar tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapMessage(in _: MessageCollectionViewCell) {
|
|
|
- print("Message tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapImage(in _: MessageCollectionViewCell) {
|
|
|
- print("Image tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapCellTopLabel(in _: MessageCollectionViewCell) {
|
|
|
- print("Top cell label tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapCellBottomLabel(in _: MessageCollectionViewCell) {
|
|
|
- print("Bottom cell label tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapMessageTopLabel(in _: MessageCollectionViewCell) {
|
|
|
- print("Top message label tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapMessageBottomLabel(in _: MessageCollectionViewCell) {
|
|
|
- print("Bottom label tapped")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapPlayButton(in cell: AudioMessageCell) {
|
|
|
- guard
|
|
|
- let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
- let message = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView)
|
|
|
- else {
|
|
|
- print("Failed to identify message when audio cell receive tap gesture")
|
|
|
- return
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func didStartAudio(in _: AudioMessageCell) {
|
|
|
- print("Did start playing audio sound")
|
|
|
- }
|
|
|
-
|
|
|
- func didPauseAudio(in _: AudioMessageCell) {
|
|
|
- print("Did pause audio sound")
|
|
|
- }
|
|
|
-
|
|
|
- func didStopAudio(in _: AudioMessageCell) {
|
|
|
- print("Did stop audio sound")
|
|
|
- }
|
|
|
-
|
|
|
- func didTapAccessoryView(in _: MessageCollectionViewCell) {
|
|
|
- print("Accessory view tapped")
|
|
|
- }
|
|
|
+ func didTapAvatar(in _: MessageCollectionViewCell) {
|
|
|
+ print("Avatar tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapMessage(in _: MessageCollectionViewCell) {
|
|
|
+ print("Message tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapImage(in _: MessageCollectionViewCell) {
|
|
|
+ print("Image tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapCellTopLabel(in _: MessageCollectionViewCell) {
|
|
|
+ print("Top cell label tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapCellBottomLabel(in _: MessageCollectionViewCell) {
|
|
|
+ print("Bottom cell label tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapMessageTopLabel(in _: MessageCollectionViewCell) {
|
|
|
+ print("Top message label tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapMessageBottomLabel(in _: MessageCollectionViewCell) {
|
|
|
+ print("Bottom label tapped")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapPlayButton(in cell: AudioMessageCell) {
|
|
|
+ guard
|
|
|
+ let indexPath = messagesCollectionView.indexPath(for: cell),
|
|
|
+ let message = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView)
|
|
|
+ else {
|
|
|
+ print("Failed to identify message when audio cell receive tap gesture")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func didStartAudio(in _: AudioMessageCell) {
|
|
|
+ print("Did start playing audio sound")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didPauseAudio(in _: AudioMessageCell) {
|
|
|
+ print("Did pause audio sound")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didStopAudio(in _: AudioMessageCell) {
|
|
|
+ print("Did stop audio sound")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didTapAccessoryView(in _: MessageCollectionViewCell) {
|
|
|
+ print("Accessory view tapped")
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
// MARK: MessageLabelDelegate
|
|
|
|
|
|
extension TSChatViewController: MessageLabelDelegate {
|
|
|
- func didSelectAddress(_ addressComponents: [String: String]) {
|
|
|
- print("Address Selected: \(addressComponents)")
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectDate(_ date: Date) {
|
|
|
- print("Date Selected: \(date)")
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectPhoneNumber(_ phoneNumber: String) {
|
|
|
- print("Phone Number Selected: \(phoneNumber)")
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectURL(_ url: URL) {
|
|
|
- print("URL Selected: \(url)")
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectTransitInformation(_ transitInformation: [String: String]) {
|
|
|
- print("TransitInformation Selected: \(transitInformation)")
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectHashtag(_ hashtag: String) {
|
|
|
- print("Hashtag selected: \(hashtag)")
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectMention(_ mention: String) {
|
|
|
- print("Mention selected: \(mention)")
|
|
|
- }
|
|
|
-
|
|
|
- func didSelectCustom(_ pattern: String, match _: String?) {
|
|
|
- print("Custom data detector patter selected: \(pattern)")
|
|
|
- }
|
|
|
+ func didSelectAddress(_ addressComponents: [String: String]) {
|
|
|
+ print("Address Selected: \(addressComponents)")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didSelectDate(_ date: Date) {
|
|
|
+ print("Date Selected: \(date)")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didSelectPhoneNumber(_ phoneNumber: String) {
|
|
|
+ print("Phone Number Selected: \(phoneNumber)")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didSelectURL(_ url: URL) {
|
|
|
+ print("URL Selected: \(url)")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didSelectTransitInformation(_ transitInformation: [String: String]) {
|
|
|
+ print("TransitInformation Selected: \(transitInformation)")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didSelectHashtag(_ hashtag: String) {
|
|
|
+ print("Hashtag selected: \(hashtag)")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didSelectMention(_ mention: String) {
|
|
|
+ print("Mention selected: \(mention)")
|
|
|
+ }
|
|
|
+
|
|
|
+ func didSelectCustom(_ pattern: String, match _: String?) {
|
|
|
+ print("Custom data detector patter selected: \(pattern)")
|
|
|
+ }
|
|
|
}
|