mirror of
https://github.com/wahyd4/Yep.git
synced 2026-08-09 04:46:35 +10:00
Merge branch 'feature/progressive_image_download' into develop
This commit is contained in:
@@ -246,6 +246,7 @@
|
||||
50AFBF4B1BB2A44C007D19DA /* InfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50AFBF4A1BB2A44C007D19DA /* InfoView.swift */; };
|
||||
50AFBF4E1BB3A594007D19DA /* bub3.caf in Resources */ = {isa = PBXBuildFile; fileRef = 50AFBF4D1BB3A594007D19DA /* bub3.caf */; };
|
||||
50AFBF5F1BB4F332007D19DA /* FeedsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50AFBF5E1BB4F332007D19DA /* FeedsViewController.swift */; };
|
||||
50B22E461C588B6200219625 /* CGImage+Yep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B22E451C588B6200219625 /* CGImage+Yep.swift */; };
|
||||
50B2CA921BD0BF3800668AC6 /* FeedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B2CA911BD0BF3800668AC6 /* FeedTextView.swift */; };
|
||||
50B2CA941BD0EF7900668AC6 /* MoreMessageTypesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B2CA931BD0EF7900668AC6 /* MoreMessageTypesView.swift */; };
|
||||
50B38FB71B69CD960064C132 /* Array+Yep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B38FB61B69CD960064C132 /* Array+Yep.swift */; };
|
||||
@@ -619,6 +620,7 @@
|
||||
50AFBF4A1BB2A44C007D19DA /* InfoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = InfoView.swift; path = Views/InfoView/InfoView.swift; sourceTree = "<group>"; };
|
||||
50AFBF4D1BB3A594007D19DA /* bub3.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = bub3.caf; path = Sounds/bub3.caf; sourceTree = "<group>"; };
|
||||
50AFBF5E1BB4F332007D19DA /* FeedsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FeedsViewController.swift; path = ViewControllers/Feeds/FeedsViewController.swift; sourceTree = "<group>"; };
|
||||
50B22E451C588B6200219625 /* CGImage+Yep.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "CGImage+Yep.swift"; path = "Extensions/CGImage+Yep.swift"; sourceTree = "<group>"; };
|
||||
50B2CA911BD0BF3800668AC6 /* FeedTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FeedTextView.swift; path = Views/TextViews/FeedTextView.swift; sourceTree = "<group>"; };
|
||||
50B2CA931BD0EF7900668AC6 /* MoreMessageTypesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MoreMessageTypesView.swift; path = Views/MoreMessageTypes/MoreMessageTypesView.swift; sourceTree = "<group>"; };
|
||||
50B38FB61B69CD960064C132 /* Array+Yep.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Array+Yep.swift"; path = "Extensions/Array+Yep.swift"; sourceTree = "<group>"; };
|
||||
@@ -1137,6 +1139,7 @@
|
||||
50DBDF041C4DD9530044E21B /* CGSize+Yep.swift */,
|
||||
5023DE511AB6C51300B3EE96 /* CGRect+Yep.swift */,
|
||||
5023DE581AB6DBC100B3EE96 /* UIImage+Yep.swift */,
|
||||
50B22E451C588B6200219625 /* CGImage+Yep.swift */,
|
||||
506EC2091AC95BFC00CE42B3 /* UIFont+Yep.swift */,
|
||||
0A3E605F1ACCA9C0003DC853 /* String+Yep.swift */,
|
||||
50A9D44A1ACD37A8000B2599 /* NSFileManager+Yep.swift */,
|
||||
@@ -2649,6 +2652,7 @@
|
||||
50CDBE421ACA9B4200459CE0 /* ChatRightImageCell.swift in Sources */,
|
||||
5099B9C41AB9510D002F940B /* RankView.swift in Sources */,
|
||||
502AE5311AB85067005BD199 /* RegisterPickMobileViewController.swift in Sources */,
|
||||
50B22E461C588B6200219625 /* CGImage+Yep.swift in Sources */,
|
||||
50535D1A1BCD19AE002FE1A4 /* TouchClosuresView.swift in Sources */,
|
||||
506E241E1AE6391A00A33C1A /* TouchZoomButton.swift in Sources */,
|
||||
5020B8A51C059662006CE8EA /* VoiceRecordSampleView.swift in Sources */,
|
||||
|
||||
@@ -213,11 +213,14 @@ class ImageCache {
|
||||
|
||||
let mediaType = message.mediaType
|
||||
|
||||
YepDownloader.downloadAttachmentsOfMessage(message, reportProgress: { progress in
|
||||
YepDownloader.downloadAttachmentsOfMessage(message, reportProgress: { progress, image in
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
completion(loadingProgress: progress, image: nil)
|
||||
completion(loadingProgress: progress, image: image)
|
||||
}
|
||||
|
||||
}, imageTransform: { image in
|
||||
return image.bubbleImageWithTailDirection(tailDirection, size: size).decodedImage()
|
||||
|
||||
}, imageFinished: { image in
|
||||
|
||||
let messageImage = image.bubbleImageWithTailDirection(tailDirection, size: size).decodedImage()
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// CGImage+Yep.swift
|
||||
// Yep
|
||||
//
|
||||
// Created by nixzhu on 16/1/27.
|
||||
// Copyright © 2016年 Catch Inc. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension CGImage {
|
||||
|
||||
var yep_extendedCanvasCGImage: CGImage {
|
||||
|
||||
let width = CGImageGetWidth(self)
|
||||
let height = CGImageGetHeight(self)
|
||||
|
||||
guard width > 0 && height > 0 else {
|
||||
return self
|
||||
}
|
||||
|
||||
func hasAlpha() -> Bool {
|
||||
let alpha = CGImageGetAlphaInfo(self)
|
||||
switch alpha {
|
||||
case .First, .Last, .PremultipliedFirst, .PremultipliedLast:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var bitmapInfo = CGBitmapInfo.ByteOrder32Little.rawValue
|
||||
if hasAlpha() {
|
||||
bitmapInfo |= CGImageAlphaInfo.PremultipliedFirst.rawValue
|
||||
} else {
|
||||
bitmapInfo |= CGImageAlphaInfo.NoneSkipFirst.rawValue
|
||||
}
|
||||
|
||||
guard let context = CGBitmapContextCreate(nil, width, height, 8, 0, CGColorSpaceCreateDeviceRGB(), bitmapInfo) else {
|
||||
return self
|
||||
}
|
||||
|
||||
CGContextDrawImage(context, CGRect(x: 0, y: 0, width: width, height: height), self)
|
||||
|
||||
guard let newCGImage = CGBitmapContextCreateImage(context) else {
|
||||
return self
|
||||
}
|
||||
|
||||
return newCGImage
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
import UIKit
|
||||
import Ruler
|
||||
import ImageIO
|
||||
import MobileCoreServices
|
||||
|
||||
extension UIImage {
|
||||
|
||||
@@ -572,3 +574,49 @@ extension UIImage {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Progressive
|
||||
|
||||
extension UIImage {
|
||||
|
||||
var yep_progressiveImage: UIImage? {
|
||||
|
||||
guard let cgImage = CGImage else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let data = NSMutableData()
|
||||
|
||||
guard let distination = CGImageDestinationCreateWithData(data, kUTTypeJPEG, 1, nil) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let jfifProperties = [
|
||||
kCGImagePropertyJFIFIsProgressive as String: kCFBooleanTrue as Bool,
|
||||
kCGImagePropertyJFIFXDensity as String: 72,
|
||||
kCGImagePropertyJFIFYDensity as String: 72,
|
||||
kCGImagePropertyJFIFDensityUnit as String: 1,
|
||||
]
|
||||
|
||||
let properties = [
|
||||
kCGImageDestinationLossyCompressionQuality as String: 0.9,
|
||||
kCGImagePropertyJFIFDictionary as String: jfifProperties,
|
||||
]
|
||||
|
||||
CGImageDestinationAddImage(distination, cgImage, properties)
|
||||
|
||||
guard CGImageDestinationFinalize(distination) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard data.length > 0 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let progressiveImage = UIImage(data: data) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return progressiveImage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
import RealmSwift
|
||||
import ImageIO
|
||||
|
||||
class YepDownloader: NSObject {
|
||||
|
||||
@@ -47,17 +48,20 @@ class YepDownloader: NSObject {
|
||||
struct ProgressReporter {
|
||||
|
||||
struct Task {
|
||||
let downloadTask: NSURLSessionDownloadTask
|
||||
let downloadTask: NSURLSessionDataTask
|
||||
|
||||
typealias FinishedAction = NSData -> Void
|
||||
let finishedAction: FinishedAction
|
||||
|
||||
let progress = NSProgress()
|
||||
let tempData = NSMutableData()
|
||||
let imageSource = CGImageSourceCreateIncremental(nil)
|
||||
let imageTransform: (UIImage -> UIImage)?
|
||||
}
|
||||
let tasks: [Task]
|
||||
var finishedTasksCount = 0
|
||||
|
||||
typealias ReportProgress = Double -> Void
|
||||
typealias ReportProgress = (progress: Double, image: UIImage?) -> Void
|
||||
let reportProgress: ReportProgress?
|
||||
|
||||
init(tasks: [Task], reportProgress: ReportProgress?) {
|
||||
@@ -77,10 +81,10 @@ class YepDownloader: NSObject {
|
||||
var progressReporters = [ProgressReporter]()
|
||||
|
||||
class func downloadAttachmentsOfMessage(message: Message, reportProgress: ProgressReporter.ReportProgress?) {
|
||||
downloadAttachmentsOfMessage(message, reportProgress: reportProgress, imageFinished: nil)
|
||||
downloadAttachmentsOfMessage(message, reportProgress: reportProgress, imageTransform: nil, imageFinished: nil)
|
||||
}
|
||||
|
||||
class func downloadAttachmentsOfMessage(message: Message, reportProgress: ProgressReporter.ReportProgress?, imageFinished: (UIImage -> Void)?) {
|
||||
class func downloadAttachmentsOfMessage(message: Message, reportProgress: ProgressReporter.ReportProgress?, imageTransform: (UIImage -> UIImage)?, imageFinished: (UIImage -> Void)?) {
|
||||
|
||||
let downloadState = message.downloadState
|
||||
|
||||
@@ -91,14 +95,14 @@ class YepDownloader: NSObject {
|
||||
let messageID = message.messageID
|
||||
let mediaType = message.mediaType
|
||||
|
||||
var attachmentDownloadTask: NSURLSessionDownloadTask?
|
||||
var attachmentDownloadTask: NSURLSessionDataTask?
|
||||
var attachmentFinishedAction: ProgressReporter.Task.FinishedAction?
|
||||
|
||||
let attachmentURLString = message.attachmentURLString
|
||||
|
||||
if !attachmentURLString.isEmpty && message.localAttachmentName.isEmpty, let URL = NSURL(string: attachmentURLString) {
|
||||
|
||||
attachmentDownloadTask = sharedDownloader.session.downloadTaskWithURL(URL)
|
||||
attachmentDownloadTask = sharedDownloader.session.dataTaskWithURL(URL)
|
||||
|
||||
attachmentFinishedAction = { data in
|
||||
|
||||
@@ -152,7 +156,7 @@ class YepDownloader: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
var thumbnailDownloadTask: NSURLSessionDownloadTask?
|
||||
var thumbnailDownloadTask: NSURLSessionDataTask?
|
||||
var thumbnailFinishedAction: ProgressReporter.Task.FinishedAction?
|
||||
|
||||
if mediaType == MessageMediaType.Video.rawValue {
|
||||
@@ -161,7 +165,7 @@ class YepDownloader: NSObject {
|
||||
|
||||
if !thumbnailURLString.isEmpty && message.localThumbnailName.isEmpty, let URL = NSURL(string: thumbnailURLString) {
|
||||
|
||||
thumbnailDownloadTask = sharedDownloader.session.downloadTaskWithURL(URL)
|
||||
thumbnailDownloadTask = sharedDownloader.session.dataTaskWithURL(URL)
|
||||
|
||||
thumbnailFinishedAction = { data in
|
||||
|
||||
@@ -196,11 +200,11 @@ class YepDownloader: NSObject {
|
||||
var tasks: [ProgressReporter.Task] = []
|
||||
|
||||
if let attachmentDownloadTask = attachmentDownloadTask, attachmentFinishedAction = attachmentFinishedAction {
|
||||
tasks.append(ProgressReporter.Task(downloadTask: attachmentDownloadTask, finishedAction: attachmentFinishedAction))
|
||||
tasks.append(ProgressReporter.Task(downloadTask: attachmentDownloadTask, finishedAction: attachmentFinishedAction, imageTransform: imageTransform))
|
||||
}
|
||||
|
||||
if let thumbnailDownloadTask = thumbnailDownloadTask, thumbnailFinishedAction = thumbnailFinishedAction {
|
||||
tasks.append(ProgressReporter.Task(downloadTask: thumbnailDownloadTask, finishedAction: thumbnailFinishedAction))
|
||||
tasks.append(ProgressReporter.Task(downloadTask: thumbnailDownloadTask, finishedAction: thumbnailFinishedAction, imageTransform: imageTransform))
|
||||
}
|
||||
|
||||
if tasks.count > 0 {
|
||||
@@ -218,8 +222,8 @@ class YepDownloader: NSObject {
|
||||
|
||||
class func downloadDataFromURL(URL: NSURL, reportProgress: ProgressReporter.ReportProgress?, finishedAction: ProgressReporter.Task.FinishedAction) {
|
||||
|
||||
let downloadTask = sharedDownloader.session.downloadTaskWithURL(URL)
|
||||
let task = ProgressReporter.Task(downloadTask: downloadTask, finishedAction: finishedAction)
|
||||
let downloadTask = sharedDownloader.session.dataTaskWithURL(URL)
|
||||
let task = ProgressReporter.Task(downloadTask: downloadTask, finishedAction: finishedAction, imageTransform: nil)
|
||||
|
||||
let progressReporter = ProgressReporter(tasks: [task], reportProgress: reportProgress)
|
||||
sharedDownloader.progressReporters.append(progressReporter)
|
||||
@@ -232,6 +236,130 @@ extension YepDownloader: NSURLSessionDelegate {
|
||||
|
||||
}
|
||||
|
||||
extension YepDownloader: NSURLSessionDataDelegate {
|
||||
|
||||
private func reportProgressAssociatedWithDownloadTask(downloadTask: NSURLSessionDataTask, totalBytes: Int64) {
|
||||
|
||||
for progressReporter in progressReporters {
|
||||
|
||||
for i in 0..<progressReporter.tasks.count {
|
||||
|
||||
if downloadTask == progressReporter.tasks[i].downloadTask {
|
||||
|
||||
progressReporter.tasks[i].progress.totalUnitCount = totalBytes
|
||||
|
||||
progressReporter.reportProgress?(progress: progressReporter.totalProgress, image: nil)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func reportProgressAssociatedWithDownloadTask(downloadTask: NSURLSessionDataTask, didReceiveData data: NSData) -> Bool {
|
||||
|
||||
for progressReporter in progressReporters {
|
||||
|
||||
for i in 0..<progressReporter.tasks.count {
|
||||
|
||||
if downloadTask == progressReporter.tasks[i].downloadTask {
|
||||
|
||||
let didReceiveDataBytes = Int64(data.length)
|
||||
progressReporter.tasks[i].progress.completedUnitCount += didReceiveDataBytes
|
||||
progressReporter.tasks[i].tempData.appendData(data)
|
||||
|
||||
let progress = progressReporter.tasks[i].progress
|
||||
let final = progress.completedUnitCount == progress.totalUnitCount
|
||||
progressReporter.reportProgress?(progress: progressReporter.totalProgress, image: nil)
|
||||
/*
|
||||
let imageSource = progressReporter.tasks[i].imageSource
|
||||
let data = progressReporter.tasks[i].tempData
|
||||
|
||||
CGImageSourceUpdateData(imageSource, data, final)
|
||||
|
||||
var tranformedImage: UIImage?
|
||||
if let cgImage = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) {
|
||||
let image = UIImage(CGImage: cgImage)
|
||||
if let imageTransform = progressReporter.tasks[i].imageTransform {
|
||||
tranformedImage = imageTransform(image)
|
||||
}
|
||||
/*
|
||||
let image = UIImage(CGImage: cgImage.yep_extendedCanvasCGImage)
|
||||
|
||||
if progressReporter.totalProgress < 1 {
|
||||
let blurPercent = CGFloat(1 - progressReporter.totalProgress)
|
||||
let radius = 5 * blurPercent
|
||||
let iterations = UInt(10 * blurPercent)
|
||||
println("radius: \(radius), iterations: \(iterations)")
|
||||
if let blurredImage = image.blurredImageWithRadius(radius, iterations: iterations, tintColor: UIColor.clearColor()) {
|
||||
if let imageTransform = progressReporter.tasks[i].imageTransform {
|
||||
tranformedImage = imageTransform(blurredImage)
|
||||
/*
|
||||
if progressReporter.totalProgress > 0.3 {
|
||||
print("imageTransform")
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
progressReporter.reportProgress?(progress: progressReporter.totalProgress, image: tranformedImage)
|
||||
*/
|
||||
|
||||
return final
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private func finishDownloadTask(downloadTask: NSURLSessionDataTask) {
|
||||
|
||||
for i in 0..<progressReporters.count {
|
||||
|
||||
for j in 0..<progressReporters[i].tasks.count {
|
||||
|
||||
if downloadTask == progressReporters[i].tasks[j].downloadTask {
|
||||
|
||||
let finishedAction = progressReporters[i].tasks[j].finishedAction
|
||||
let data = progressReporters[i].tasks[j].tempData
|
||||
finishedAction(data)
|
||||
|
||||
progressReporters[i].finishedTasksCount++
|
||||
|
||||
// 若任务都已完成,移除此 progressReporter
|
||||
if progressReporters[i].finishedTasksCount == progressReporters[i].tasks.count {
|
||||
progressReporters.removeAtIndex(i)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {
|
||||
println("YepDownloader begin, expectedContentLength:\(response.expectedContentLength)")
|
||||
reportProgressAssociatedWithDownloadTask(dataTask, totalBytes: response.expectedContentLength)
|
||||
completionHandler(.Allow)
|
||||
}
|
||||
|
||||
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
|
||||
println("YepDownloader data.length: \(data.length)")
|
||||
|
||||
let finish = reportProgressAssociatedWithDownloadTask(dataTask, didReceiveData: data)
|
||||
|
||||
if finish {
|
||||
println("YepDownloader finish")
|
||||
|
||||
finishDownloadTask(dataTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
extension YepDownloader: NSURLSessionDownloadDelegate {
|
||||
|
||||
private func handleData(data: NSData, ofDownloadTask downloadTask: NSURLSessionDownloadTask) {
|
||||
@@ -300,4 +428,4 @@ extension YepDownloader: NSURLSessionDownloadDelegate {
|
||||
reportProgressAssociatedWithDownloadTask(downloadTask, totalBytesWritten: totalBytesWritten, totalBytesExpectedToWrite: totalBytesExpectedToWrite)
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
@@ -4633,6 +4633,14 @@ extension ConversationViewController: UIImagePickerControllerDelegate, UINavigat
|
||||
// Do send
|
||||
|
||||
let imageData = UIImageJPEGRepresentation(image, YepConfig.messageImageCompressionQuality())!
|
||||
/*
|
||||
var imageData = UIImageJPEGRepresentation(image, YepConfig.messageImageCompressionQuality())!
|
||||
|
||||
if let progressiveImage = UIImage(data: imageData)?.yep_progressiveImage {
|
||||
|
||||
imageData = UIImageJPEGRepresentation(progressiveImage, YepConfig.messageImageCompressionQuality())!
|
||||
}
|
||||
*/
|
||||
|
||||
let messageImageName = NSUUID().UUIDString
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ class ChatLeftAudioCell: ChatBaseCell {
|
||||
|
||||
self.audioPlayedDuration = audioPlayedDuration
|
||||
|
||||
YepDownloader.downloadAttachmentsOfMessage(message, reportProgress: { [weak self] progress in
|
||||
YepDownloader.downloadAttachmentsOfMessage(message, reportProgress: { [weak self] progress, _ in
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
self?.loadingWithProgress(progress)
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ class ChatRightAudioCell: ChatRightBaseCell {
|
||||
|
||||
self.audioPlayedDuration = audioPlayedDuration
|
||||
|
||||
YepDownloader.downloadAttachmentsOfMessage(message, reportProgress: { _ in })
|
||||
YepDownloader.downloadAttachmentsOfMessage(message, reportProgress: { _, _ in })
|
||||
|
||||
UIView.performWithoutAnimation { [weak self] in
|
||||
self?.makeUI()
|
||||
|
||||
Reference in New Issue
Block a user