Merge branch 'charlesmchen/improveAttachmentApprovalView'

pull/1/head
Matthew Chen 8 years ago
commit 9882eeea93

@ -7,6 +7,7 @@
#import "Asserts.h" #import "Asserts.h"
#import "AttachmentSharing.h" #import "AttachmentSharing.h"
#import "Environment.h" #import "Environment.h"
#import "FLAnimatedImage.h"
#import "NotificationsManager.h" #import "NotificationsManager.h"
#import "OWSAnyTouchGestureRecognizer.h" #import "OWSAnyTouchGestureRecognizer.h"
#import "OWSCallNotificationsAdaptee.h" #import "OWSCallNotificationsAdaptee.h"

@ -3,6 +3,7 @@
// //
import Foundation import Foundation
import MediaPlayer
class AttachmentApprovalViewController: UIViewController { class AttachmentApprovalViewController: UIViewController {
@ -14,6 +15,8 @@ class AttachmentApprovalViewController: UIViewController {
var successCompletion : (() -> Void)? var successCompletion : (() -> Void)?
var videoPlayer: MPMoviePlayerController?
// MARK: Initializers // MARK: Initializers
@available(*, unavailable, message:"use attachment: constructor instead.") @available(*, unavailable, message:"use attachment: constructor instead.")
@ -60,29 +63,75 @@ class AttachmentApprovalViewController: UIViewController {
createButtonRow(attachmentPreviewView:attachmentPreviewView) createButtonRow(attachmentPreviewView:attachmentPreviewView)
if attachment.isImage { if attachment.isAnimatedImage {
createAnimatedPreview(attachmentPreviewView:attachmentPreviewView)
} else if attachment.isImage {
createImagePreview(attachmentPreviewView:attachmentPreviewView) createImagePreview(attachmentPreviewView:attachmentPreviewView)
} else if attachment.isVideo {
createVideoPreview(attachmentPreviewView:attachmentPreviewView)
} else if attachment.isAudio {
createAudioPreview(attachmentPreviewView:attachmentPreviewView)
} else { } else {
createGenericPreview(attachmentPreviewView:attachmentPreviewView) createGenericPreview(attachmentPreviewView:attachmentPreviewView)
} }
} }
private func createAudioPreview(attachmentPreviewView: UIView) {
// TODO: Add audio player.
createGenericPreview(attachmentPreviewView:attachmentPreviewView)
}
private func createAnimatedPreview(attachmentPreviewView: UIView) {
// Use Flipboard FLAnimatedImage library to display gifs
guard let animatedImage = FLAnimatedImage(gifData:attachment.data) else {
createGenericPreview(attachmentPreviewView:attachmentPreviewView)
return
}
let animatedImageView = FLAnimatedImageView()
animatedImageView.animatedImage = animatedImage
animatedImageView.contentMode = .scaleAspectFit
attachmentPreviewView.addSubview(animatedImageView)
animatedImageView.autoPinWidthToSuperview()
animatedImageView.autoPinHeightToSuperview()
}
private func createImagePreview(attachmentPreviewView: UIView) { private func createImagePreview(attachmentPreviewView: UIView) {
var image = attachment.image var image = attachment.image
if image == nil { if image == nil {
image = UIImage(data:attachment.data) image = UIImage(data:attachment.data)
} }
if image != nil { guard image != nil else {
let imageView = UIImageView(image:image) createGenericPreview(attachmentPreviewView:attachmentPreviewView)
imageView.layer.minificationFilter = kCAFilterTrilinear return
imageView.layer.magnificationFilter = kCAFilterTrilinear }
imageView.contentMode = .scaleAspectFit
attachmentPreviewView.addSubview(imageView) let imageView = UIImageView(image:image)
imageView.autoPinWidthToSuperview() imageView.layer.minificationFilter = kCAFilterTrilinear
imageView.autoPinHeightToSuperview() imageView.layer.magnificationFilter = kCAFilterTrilinear
} else { 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) 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) { private func createGenericPreview(attachmentPreviewView: UIView) {
@ -125,9 +174,17 @@ class AttachmentApprovalViewController: UIViewController {
let numberFormatter = NumberFormatter() let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = NumberFormatter.Style.decimal numberFormatter.numberStyle = NumberFormatter.Style.decimal
let fileSizeLabel = UILabel() let fileSizeLabel = UILabel()
let fileSize = attachment.data.count
let kOneKilobyte = 1024
let kOneMegabyte = kOneKilobyte * kOneKilobyte
let fileSizeText = (fileSize > kOneMegabyte
? numberFormatter.string(from: NSNumber(value: fileSize / kOneMegabyte))! + " mb"
: (fileSize > kOneKilobyte
? numberFormatter.string(from: NSNumber(value: fileSize / kOneKilobyte))! + " kb"
: numberFormatter.string(from: NSNumber(value: fileSize))!))
fileSizeLabel.text = String(format:NSLocalizedString("ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT", fileSizeLabel.text = String(format:NSLocalizedString("ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT",
comment: "Format string for file size label in call interstitial view"), comment: "Format string for file size label in call interstitial view. Embeds: {{file size as 'N mb' or 'N kb'}}."),
numberFormatter.string(from: NSNumber(value: attachment.data.count))!) fileSizeText)
fileSizeLabel.textColor = UIColor.white fileSizeLabel.textColor = UIColor.white
fileSizeLabel.font = labelFont fileSizeLabel.font = labelFont

@ -110,12 +110,9 @@ typedef enum : NSUInteger {
} }
- (BOOL)pasteBoardHasPossibleAttachment { - (BOOL)pasteBoardHasPossibleAttachment {
if ([SignalAttachment pasteboardHasPossibleAttachment]) { // We don't want to load/convert images more than once so we
// We don't want to load/convert images more than once so we // only do a cursory validation pass at this time.
// only do a cursory validation pass at this time. return [SignalAttachment pasteboardHasPossibleAttachment];
return YES;
}
return NO;
} }
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { - (BOOL)canPerformAction:(SEL)action withSender:(id)sender {

@ -64,6 +64,8 @@ class SignalAttachment: NSObject {
let data: Data let data: Data
internal var temporaryDataUrl: URL?
// Attachment types are identified using UTIs. // Attachment types are identified using UTIs.
// //
// See: https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html // See: https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html
@ -109,6 +111,30 @@ class SignalAttachment: NSObject {
super.init() 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.error("\(SignalAttachment.TAG) Could not write data to disk: \(dataUTI)")
assertionFailure()
return nil
}
temporaryDataUrl = fileUrl
}
return temporaryDataUrl
}
var hasError: Bool { var hasError: Bool {
return error != nil return error != nil
} }
@ -237,6 +263,10 @@ class SignalAttachment: NSObject {
return SignalAttachment.outputImageUTISet.contains(dataUTI) return SignalAttachment.outputImageUTISet.contains(dataUTI)
} }
public var isAnimatedImage: Bool {
return SignalAttachment.animatedImageUTISet.contains(dataUTI)
}
public var isVideo: Bool { public var isVideo: Bool {
return SignalAttachment.videoUTISet.contains(dataUTI) return SignalAttachment.videoUTISet.contains(dataUTI)
} }

@ -56,7 +56,7 @@
"ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "File type: %@"; "ATTACHMENT_APPROVAL_FILE_EXTENSION_FORMAT" = "File type: %@";
/* Format string for file size label in call interstitial view */ /* Format string for file size label in call interstitial view */
"ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "File size: %@"; "ATTACHMENT_APPROVAL_FILE_SIZE_FORMAT" = "Size: %@";
/* Label for 'send' button in the 'attachment approval' dialog. */ /* Label for 'send' button in the 'attachment approval' dialog. */
"ATTACHMENT_APPROVAL_SEND_BUTTON" = "Send"; "ATTACHMENT_APPROVAL_SEND_BUTTON" = "Send";

Loading…
Cancel
Save