From 5d79f43970b9782e8e7e74b44aa8d3b6d00d2744 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 12 Apr 2017 16:30:25 -0400 Subject: [PATCH] Add video preview to attachment approval dialog. // FREEBIE --- .../AttachmentApprovalViewController.swift | 44 +++++++++++++++---- .../ViewControllers/SignalAttachment.swift | 25 +++++++++++ 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/Signal/src/ViewControllers/AttachmentApprovalViewController.swift b/Signal/src/ViewControllers/AttachmentApprovalViewController.swift index b6df468b5..07cd6c38d 100644 --- a/Signal/src/ViewControllers/AttachmentApprovalViewController.swift +++ b/Signal/src/ViewControllers/AttachmentApprovalViewController.swift @@ -3,6 +3,7 @@ // import Foundation +import MediaPlayer class AttachmentApprovalViewController: UIViewController { @@ -14,6 +15,8 @@ class AttachmentApprovalViewController: UIViewController { var successCompletion : (() -> Void)? + var videoPlayer: MPMoviePlayerController? + // MARK: Initializers @available(*, unavailable, message:"use attachment: constructor instead.") @@ -62,6 +65,8 @@ class AttachmentApprovalViewController: UIViewController { if attachment.isImage { createImagePreview(attachmentPreviewView:attachmentPreviewView) + } else if attachment.isVideo { + createVideoPreview(attachmentPreviewView:attachmentPreviewView) } else { createGenericPreview(attachmentPreviewView:attachmentPreviewView) } @@ -72,17 +77,38 @@ class AttachmentApprovalViewController: UIViewController { if image == nil { image = UIImage(data:attachment.data) } - if image != nil { - let imageView = UIImageView(image:image) - imageView.layer.minificationFilter = kCAFilterTrilinear - imageView.layer.magnificationFilter = kCAFilterTrilinear - imageView.contentMode = .scaleAspectFit - attachmentPreviewView.addSubview(imageView) - imageView.autoPinWidthToSuperview() - imageView.autoPinHeightToSuperview() - } else { + guard image != nil else { + createGenericPreview(attachmentPreviewView:attachmentPreviewView) + return + } + + let imageView = UIImageView(image:image) + imageView.layer.minificationFilter = kCAFilterTrilinear + imageView.layer.magnificationFilter = kCAFilterTrilinear + imageView.contentMode = .scaleAspectFit + attachmentPreviewView.addSubview(imageView) + imageView.autoPinWidthToSuperview() + imageView.autoPinHeightToSuperview() + } + + private func createVideoPreview(attachmentPreviewView: UIView) { + guard let dataUrl = attachment.getTemporaryDataUrl() else { createGenericPreview(attachmentPreviewView:attachmentPreviewView) + return } + guard let videoPlayer = MPMoviePlayerController(contentURL:dataUrl) else { + createGenericPreview(attachmentPreviewView:attachmentPreviewView) + return + } + videoPlayer.prepareToPlay() + + videoPlayer.controlStyle = .default + videoPlayer.shouldAutoplay = false + + attachmentPreviewView.addSubview(videoPlayer.view) + self.videoPlayer = videoPlayer + videoPlayer.view.autoPinWidthToSuperview() + videoPlayer.view.autoPinHeightToSuperview() } private func createGenericPreview(attachmentPreviewView: UIView) { diff --git a/Signal/src/ViewControllers/SignalAttachment.swift b/Signal/src/ViewControllers/SignalAttachment.swift index 7fd436663..a87cf3326 100644 --- a/Signal/src/ViewControllers/SignalAttachment.swift +++ b/Signal/src/ViewControllers/SignalAttachment.swift @@ -64,6 +64,8 @@ class SignalAttachment: NSObject { let data: Data + internal var temporaryDataUrl: URL? + // Attachment types are identified using UTIs. // // See: https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html @@ -109,6 +111,29 @@ class SignalAttachment: NSObject { super.init() } + // MARK: Methods + + public func getTemporaryDataUrl() -> URL? { + if temporaryDataUrl == nil { + let directory = NSTemporaryDirectory() + guard let fileExtension = self.fileExtension else { + return nil + } + let fileName = NSUUID().uuidString + "." + fileExtension + guard let fileUrl = NSURL.fileURL(withPathComponents: [directory, fileName]) else { + return nil + } + do { + try data.write(to: fileUrl) + } catch { + Logger.info("\(SignalAttachment.TAG) Could not write data to disk: \(dataUTI)") + return nil + } + temporaryDataUrl = fileUrl + } + return temporaryDataUrl + } + var hasError: Bool { return error != nil }