fix image, video, audio interactions in message details

// FREEBIE
pull/1/head
Michael Kirk 7 years ago
parent 7abd51838f
commit 1780973e68

@ -52,6 +52,7 @@
#import <SignalMessaging/ContactTableViewCell.h>
#import <SignalMessaging/Environment.h>
#import <SignalMessaging/NSString+OWS.h>
#import <SignalMessaging/OWSAudioPlayer.h>
#import <SignalMessaging/OWSContactAvatarBuilder.h>
#import <SignalMessaging/OWSContactsManager.h>
#import <SignalMessaging/OWSFormat.h>

@ -12,7 +12,8 @@ enum MessageMetadataViewMode: UInt {
case focusOnMetadata
}
class MessageDetailViewController: OWSViewController, MediaDetailPresenter, MediaGalleryDataSourceDelegate {
//class MessageDetailViewController: OWSViewController, MediaDetailPresenter, MediaGalleryDataSourceDelegate {
class MessageDetailViewController: OWSViewController, MediaGalleryDataSourceDelegate, OWSMessageBubbleViewDelegate {
// MARK: Properties
@ -318,30 +319,29 @@ class MessageDetailViewController: OWSViewController, MediaDetailPresenter, Medi
rows += addAttachmentRows()
}
if true {
let messageBubbleView = OWSMessageBubbleView(frame: CGRect.zero)
self.messageBubbleView = messageBubbleView
messageBubbleView.viewItem = viewItem
messageBubbleView.cellMediaCache = NSCache()
messageBubbleView.contentWidth = contentWidth()
messageBubbleView.alwaysShowBubbleTail = true
messageBubbleView.configureViews()
messageBubbleView.loadContent()
let messageBubbleView = OWSMessageBubbleView(frame: CGRect.zero)
messageBubbleView.delegate = self
self.messageBubbleView = messageBubbleView
messageBubbleView.viewItem = viewItem
messageBubbleView.cellMediaCache = NSCache()
messageBubbleView.contentWidth = contentWidth()
messageBubbleView.alwaysShowBubbleTail = true
messageBubbleView.configureViews()
messageBubbleView.loadContent()
messageBubbleView.isUserInteractionEnabled = true
messageBubbleView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(messageBubbleTapped)))
assert(messageBubbleView.isUserInteractionEnabled)
// messageBubbleView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(messageBubbleTapped)))
let row = UIView()
row.addSubview(messageBubbleView)
messageBubbleView.autoPinHeightToSuperview()
let row = UIView()
row.addSubview(messageBubbleView)
messageBubbleView.autoPinHeightToSuperview()
let isIncoming = self.message as? TSIncomingMessage != nil
messageBubbleView.autoPinEdge(toSuperviewEdge: isIncoming ? .leading : .trailing, withInset: bubbleViewHMargin)
let isIncoming = self.message as? TSIncomingMessage != nil
messageBubbleView.autoPinEdge(toSuperviewEdge: isIncoming ? .leading : .trailing, withInset: bubbleViewHMargin)
self.messageBubbleViewWidthLayoutConstraint = messageBubbleView.autoSetDimension(.width, toSize: 0)
self.messageBubbleViewHeightLayoutConstraint = messageBubbleView.autoSetDimension(.height, toSize: 0)
rows.append(row)
}
self.messageBubbleViewWidthLayoutConstraint = messageBubbleView.autoSetDimension(.width, toSize: 0)
self.messageBubbleViewHeightLayoutConstraint = messageBubbleView.autoSetDimension(.height, toSize: 0)
rows.append(row)
if rows.count == 0 {
// Neither attachment nor body.
@ -587,40 +587,112 @@ class MessageDetailViewController: OWSViewController, MediaDetailPresenter, Medi
messageBubbleViewHeightLayoutConstraint.constant = messageBubbleSize.height
}
// MARK: - Event Handlers
// // MARK: - Event Handlers
//
// func messageBubbleTapped(sender: UIGestureRecognizer) {
// guard let messageBubbleView = messageBubbleView else {
// return
// }
// guard sender.state == .recognized else {
// return
// }
// if let outgoingMessage = viewItem.interaction as? TSOutgoingMessage {
// switch outgoingMessage.messageState {
// case .attemptingOut,
// .unsent:
// // Ignore taps on "unsent" and "sending" messages.
// return
// default:
// break
// }
// }
//
// let locationInMessageBubble = sender.location(in: messageBubbleView)
// switch messageBubbleView.gestureLocation(forLocation: locationInMessageBubble) {
// case .default:
// break
// case .oversizeText:
// let viewController = LongTextViewController(viewItem: viewItem)
// self.navigationController?.pushViewController(viewController, animated: true)
// break
// case .media:
// // TODO: We could show MediaGalleryViewController?
// break
// case .quotedReply:
// break
// }
// }
// MARK: OWSMessageBubbleViewDelegate
func didTapImageViewItem(_ viewItem: ConversationViewItem, attachmentStream: TSAttachmentStream, imageView: UIView) {
let mediaGalleryViewController = MediaGalleryViewController(thread: self.thread, uiDatabaseConnection: self.uiDatabaseConnection)
mediaGalleryViewController.addDataSourceDelegate(self)
mediaGalleryViewController.presentDetailView(fromViewController: self, mediaMessage: self.message, replacingView: imageView)
}
func messageBubbleTapped(sender: UIGestureRecognizer) {
guard let messageBubbleView = messageBubbleView else {
func didTapVideoViewItem(_ viewItem: ConversationViewItem, attachmentStream: TSAttachmentStream, imageView: UIView) {
let mediaGalleryViewController = MediaGalleryViewController(thread: self.thread, uiDatabaseConnection: self.uiDatabaseConnection)
mediaGalleryViewController.addDataSourceDelegate(self)
mediaGalleryViewController.presentDetailView(fromViewController: self, mediaMessage: self.message, replacingView: imageView)
}
var audioAttachmentPlayer: OWSAudioPlayer?
func didTapAudioViewItem(_ viewItem: ConversationViewItem, attachmentStream: TSAttachmentStream) {
AssertIsOnMainThread()
guard let mediaURL = attachmentStream.mediaURL() else {
owsFail("\(logTag) in \(#function) mediaURL was unexpectedly nil for attachment: \(attachmentStream)")
return
}
guard sender.state == .recognized else {
guard FileManager.default.fileExists(atPath: mediaURL.path) else {
owsFail("\(logTag) in \(#function) audio file missing at path: \(mediaURL)")
return
}
if let outgoingMessage = viewItem.interaction as? TSOutgoingMessage {
switch outgoingMessage.messageState {
case .attemptingOut,
.unsent:
// Ignore taps on "unsent" and "sending" messages.
if let audioAttachmentPlayer = self.audioAttachmentPlayer {
// Is this player associated with this media adapter?
if (audioAttachmentPlayer.owner as? ConversationViewItem == viewItem) {
// Tap to pause & unpause.
audioAttachmentPlayer.togglePlayState()
return
default:
break
}
audioAttachmentPlayer.stop()
self.audioAttachmentPlayer = nil
}
let locationInMessageBubble = sender.location(in: messageBubbleView)
switch messageBubbleView.gestureLocation(forLocation: locationInMessageBubble) {
case .default:
break
case .oversizeText:
let viewController = LongTextViewController(viewItem: viewItem)
self.navigationController?.pushViewController(viewController, animated: true)
break
case .media:
// TODO: We could show MediaGalleryViewController?
break
case .quotedReply:
break
let audioAttachmentPlayer = OWSAudioPlayer(mediaUrl: mediaURL, delegate: viewItem)
self.audioAttachmentPlayer = audioAttachmentPlayer
// Associate the player with this media adapter.
audioAttachmentPlayer.owner = viewItem
audioAttachmentPlayer.playWithPlaybackAudioCategory()
}
func didTapTruncatedTextMessage(_ conversationItem: ConversationViewItem) {
guard let navigationController = self.navigationController else {
owsFail("\(logTag) in \(#function) navigationController was unexpectedly nil")
return
}
let viewController = LongTextViewController(viewItem: viewItem)
navigationController.pushViewController(viewController, animated: true)
}
func didTapFailedIncomingAttachment(_ viewItem: ConversationViewItem, attachmentPointer: TSAttachmentPointer) {
// no - op
}
func didTapFailedOutgoingMessage(_ message: TSOutgoingMessage) {
// no - op
}
func didTapQuotedMessage(_ viewItem: ConversationViewItem, quotedMessage: TSQuotedMessage) {
// no - op
}
// MediaGalleryDataSourceDelegate
@ -643,16 +715,16 @@ class MessageDetailViewController: OWSViewController, MediaDetailPresenter, Medi
}
}
// MARK: MediaDetailPresenter
public func presentDetails(mediaMessageView: MediaMessageView, fromView: UIView) {
guard self.attachmentStream != nil else {
owsFail("attachment stream unexpectedly nil")
return
}
let mediaGalleryViewController = MediaGalleryViewController(thread: self.thread, uiDatabaseConnection: self.uiDatabaseConnection)
mediaGalleryViewController.addDataSourceDelegate(self)
mediaGalleryViewController.presentDetailView(fromViewController: self, mediaMessage: self.message, replacingView: fromView)
}
// // MARK: MediaDetailPresenter
//
// public func presentDetails(mediaMessageView: MediaMessageView, fromView: UIView) {
// guard self.attachmentStream != nil else {
// owsFail("attachment stream unexpectedly nil")
// return
// }
//
// let mediaGalleryViewController = MediaGalleryViewController(thread: self.thread, uiDatabaseConnection: self.uiDatabaseConnection)
// mediaGalleryViewController.addDataSourceDelegate(self)
// mediaGalleryViewController.presentDetailView(fromViewController: self, mediaMessage: self.message, replacingView: fromView)
// }
}

@ -30,6 +30,7 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
#import <SignalMessaging/OWSLogger.h>
#import <SignalMessaging/OWSMath.h>
#import <SignalMessaging/OWSProfileManager.h>
#import <SignalMessaging/OWSQuotedReplyModel.h>
#import <SignalMessaging/OWSSounds.h>
#import <SignalMessaging/OWSTableViewController.h>
#import <SignalMessaging/OWSUserProfile.h>

@ -14,10 +14,10 @@ public enum MediaMessageViewMode: UInt {
case attachmentApproval
}
@objc
public protocol MediaDetailPresenter: class {
func presentDetails(mediaMessageView: MediaMessageView, fromView: UIView)
}
//@objc
//public protocol MediaDetailPresenter: class {
// func presentDetails(mediaMessageView: MediaMessageView, fromView: UIView)
//}
@objc
public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
@ -59,7 +59,7 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
@objc
public var contentView: UIView?
private weak var mediaDetailPresenter: MediaDetailPresenter?
// private weak var mediaDetailPresenter: MediaDetailPresenter?
// MARK: Initializers
@ -68,16 +68,18 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
fatalError("\(#function) is unimplemented.")
}
@objc
public convenience init(attachment: SignalAttachment, mode: MediaMessageViewMode) {
self.init(attachment: attachment, mode: mode, mediaDetailPresenter: nil)
}
// @objc
// public convenience init(attachment: SignalAttachment, mode: MediaMessageViewMode) {
// self.init(attachment: attachment, mode: mode, mediaDetailPresenter: nil)
// }
public required init(attachment: SignalAttachment, mode: MediaMessageViewMode, mediaDetailPresenter: MediaDetailPresenter?) {
// TODO there's only one mode now, used by the AttachmentApprovalView
@objc
public required init(attachment: SignalAttachment, mode: MediaMessageViewMode) { //}, mediaDetailPresenter: MediaDetailPresenter?) {
assert(!attachment.hasError)
self.attachment = attachment
self.mode = mode
self.mediaDetailPresenter = mediaDetailPresenter
// self.mediaDetailPresenter = mediaDetailPresenter
super.init(frame: CGRect.zero)
createViews()
@ -203,9 +205,9 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
let aspectRatio = image.size.width / image.size.height
addSubviewWithScaleAspectFitLayout(view: animatedImageView, aspectRatio: aspectRatio)
contentView = animatedImageView
animatedImageView.isUserInteractionEnabled = true
animatedImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imageTapped)))
//
// animatedImageView.isUserInteractionEnabled = true
// animatedImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imageTapped)))
}
private func addSubviewWithScaleAspectFitLayout(view: UIView, aspectRatio: CGFloat) {
@ -237,9 +239,9 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
let aspectRatio = image.size.width / image.size.height
addSubviewWithScaleAspectFitLayout(view: imageView, aspectRatio: aspectRatio)
contentView = imageView
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imageTapped)))
//
// imageView.isUserInteractionEnabled = true
// imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imageTapped)))
}
private func createVideoPreview() {
@ -269,8 +271,8 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
self.addSubview(videoPlayButton)
videoPlayButton.autoCenterInSuperview()
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(videoTapped)))
// imageView.isUserInteractionEnabled = true
// imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(videoTapped)))
}
}
@ -445,44 +447,43 @@ public class MediaMessageView: UIView, OWSAudioPlayerDelegate {
audioPlayButton?.setImage(image, for: .normal)
audioPlayButton?.imageView?.tintColor = controlTintColor
}
// MARK: - Full Screen Image
@objc
func imageTapped(sender: UIGestureRecognizer) {
// Approval view handles it's own zooming gesture
guard mode != .attachmentApproval else {
return
}
guard sender.state == .recognized else {
return
}
guard let fromView = sender.view else {
return
}
showMediaDetailViewController(fromView: fromView)
}
// MARK: - Video Playback
@objc
func videoTapped(sender: UIGestureRecognizer) {
// Approval view handles it's own play gesture
guard mode != .attachmentApproval else {
return
}
guard sender.state == .recognized else {
return
}
guard let fromView = sender.view else {
return
}
showMediaDetailViewController(fromView: fromView)
}
func showMediaDetailViewController(fromView: UIView) {
self.mediaDetailPresenter?.presentDetails(mediaMessageView: self, fromView: fromView)
}
//
// // MARK: - Full Screen Image
//
// @objc
// func imageTapped(sender: UIGestureRecognizer) {
// // Approval view handles it's own zooming gesture
// guard mode != .attachmentApproval else {
// return
// }
// guard sender.state == .recognized else {
// return
// }
// guard let fromView = sender.view else {
// return
// }
//
// showMediaDetailViewController(fromView: fromView)
// }
//
// // MARK: - Video Playback
//
// @objc
// func videoTapped(sender: UIGestureRecognizer) {
// // Approval view handles it's own play gesture
// guard mode != .attachmentApproval else {
// return
// }
// guard sender.state == .recognized else {
// return
// }
// guard let fromView = sender.view else {
// return
// }
//
// showMediaDetailViewController(fromView: fromView)
// }
// func showMediaDetailViewController(fromView: UIView) {
// self.mediaDetailPresenter?.presentDetails(mediaMessageView: self, fromView: fromView)
// }
}

Loading…
Cancel
Save