Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
to use, copy
public var thumbnail: UIImage

public var thumbnailURL: String?
, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

Expand All @@ -28,6 +32,8 @@ public protocol PhotoMessageModelProtocol: DecoratedMessageModelProtocol {
var image: UIImage { get }
var imageSize: CGSize { get }
var imageURL: String? { get }
var thumbnail: UIImage { get }
var thumbnailURL: String? { get }
}

open class PhotoMessageModel<MessageModelT: MessageModelProtocol>: PhotoMessageModelProtocol {
Expand All @@ -38,10 +44,15 @@ open class PhotoMessageModel<MessageModelT: MessageModelProtocol>: PhotoMessageM
public var image: UIImage
public let imageSize: CGSize
public var imageURL: String?
public init(messageModel: MessageModelT, imageSize: CGSize, image: UIImage, imageURL: String?) {
public var thumbnail: UIImage
public var thumbnailURL: String?

public init(messageModel: MessageModelT, imageSize: CGSize, image: UIImage, imageURL: String?, thumbnailURL: String?) {
self._messageModel = messageModel
self.imageSize = imageSize
self.image = image
self.imageURL = imageURL
self.thumbnail = image
self.thumbnailURL = thumbnailURL
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ open class PhotoTextMessageModel<MessageModelT: MessageModelProtocol>: PhotoText
public var image: UIImage
public let imageSize: CGSize
public var imageURL: String?
public init(messageModel: MessageModelT, text: String, imageSize: CGSize, image: UIImage, imageURL: String?) {
public var thumbnail: UIImage
public var thumbnailURL: String?


public init(messageModel: MessageModelT, text: String, imageSize: CGSize, image: UIImage, imageURL: String?, thumbnailURL: String?) {
self._messageModel = messageModel
self.text = text
self.imageSize = imageSize
self.image = image
self.imageURL = imageURL
self.thumbnail = image
self.thumbnailURL = thumbnailURL
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,15 @@ private final class ChatMessageTextView: UITextView {
super.gestureRecognizers = newValue
}
get {
return super.gestureRecognizers?.filter({ (gestureRecognizer) -> Bool in
return type(of: gestureRecognizer) == UILongPressGestureRecognizer.self && gestureRecognizer.delaysTouchesEnded
})
return super.gestureRecognizers?.filter { gestureRecognizer in
if type(of: gestureRecognizer) == UILongPressGestureRecognizer.self, gestureRecognizer.delaysTouchesEnded {
return true
}
if #available(iOS 11, *), gestureRecognizer.name == "UITextInteractionNameLinkTap" {
return true
}
return false
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,24 @@ open class VideoTextMessageModel<MessageModelT: MessageModelProtocol>: VideoText
public var image: UIImage
public let imageSize: CGSize
public var imageURL: String?
public var thumbnail: UIImage
public var thumbnailURL: String?
public var videoURL: URL?

public init(messageModel: MessageModelT,
text: String,
videoURL: URL,
imageSize: CGSize,
image: UIImage,
imageURL: String?)
thumbnail: UIImage,
thumbnailURL: String?)
{
self._messageModel = messageModel
self.text = text
self.imageSize = imageSize
self.image = image
self.imageURL = imageURL
self.image = thumbnail
self.thumbnail = thumbnail
self.imageURL = thumbnailURL
self.thumbnailURL = thumbnailURL
self.videoURL = videoURL
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ final class PhotosInputCell: UICollectionViewCell {
}
set {
self.imageView.image = newValue
if (newValue != nil) {
self.imageView.startAnimating()
} else {
self.imageView.stopAnimating()
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ final class PhotosInputDataProvider: NSObject, PhotosInputDataProviderProtocol,
}

func requestPreviewImage(at index: Int,
targetSize: CGSize,
targetSize: CGSize,
completion: @escaping PhotosInputDataProviderCompletion) -> PhotosInputDataProviderImageRequestProtocol {
assert(index >= 0 && index < self.fetchResult.count, "Index out of bounds")
let asset = self.fetchResult[index]
Expand Down Expand Up @@ -134,8 +134,18 @@ final class PhotosInputDataProvider: NSObject, PhotosInputDataProviderProtocol,
requestId = self.imageManager.requestImageData(for: asset, options: options, resultHandler: { [weak self] (data, _, _, info) in
guard let sSelf = self else { return }
let result: PhotosInputDataProviderResult
if let data = data, let image = UIImage(data: data) {
result = .success(image)
if let data = data {
if UIImage.isAnimatedImage(data) {
if let gifImage = UIImage.gifImageWithData(data: data) {
result = .success(gifImage)
} else {
result = .error(info?[PHImageErrorKey] as? Error)
}
} else if let image = UIImage(data: data) {
result = .success(image)
} else {
result = .error(info?[PHImageErrorKey] as? Error)
}
} else {
result = .error(info?[PHImageErrorKey] as? Error)
}
Expand Down Expand Up @@ -194,3 +204,129 @@ final class PhotosInputDataProvider: NSObject, PhotosInputDataProviderProtocol,
}
}
}

public extension UIImage {

class func isAnimatedImage(_ data: Data) -> Bool {
if let source = CGImageSourceCreateWithData(data as CFData, nil) {
let count = CGImageSourceGetCount(source)
return count > 1
}
return false
}

class func gifImageWithData(data: Data) -> UIImage? {
guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {
print("image doesn't exist")
return nil
}

return UIImage.animatedImageWithSource(source: source)
}

class func animatedImageWithSource(source: CGImageSource) -> UIImage? {
let count = CGImageSourceGetCount(source)
var images = [CGImage]()
var delays = [Int]()

for i in 0..<count {
if let image = CGImageSourceCreateImageAtIndex(source, i, nil) {
images.append(image)
}

let delaySeconds = UIImage.delayForImageAtIndex(index: Int(i), source: source)
delays.append(Int(delaySeconds * 1000.0)) // Seconds to ms
}

let duration: Int = {
var sum = 0

for val: Int in delays {
sum += val
}

return sum
}()

let gcd = gcdForArray(array: delays)
var frames = [UIImage]()

var frame: UIImage
var frameCount: Int
for i in 0..<count {
frame = UIImage(cgImage: images[Int(i)])
frameCount = Int(delays[Int(i)] / gcd)

for _ in 0..<frameCount {
frames.append(frame)
}
}

let animation = UIImage.animatedImage(with: frames, duration: Double(duration) / 1000.0)

return animation
}

class func delayForImageAtIndex(index: Int, source: CGImageSource!) -> Double {
var delay = 0.1

let cfProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil)
let gifProperties: CFDictionary = unsafeBitCast(CFDictionaryGetValue(cfProperties, Unmanaged.passUnretained(kCGImagePropertyGIFDictionary).toOpaque()), to: CFDictionary.self)

var delayObject: AnyObject = unsafeBitCast(CFDictionaryGetValue(gifProperties, Unmanaged.passUnretained(kCGImagePropertyGIFUnclampedDelayTime).toOpaque()), to: AnyObject.self)

if delayObject.doubleValue == 0 {
delayObject = unsafeBitCast(CFDictionaryGetValue(gifProperties, Unmanaged.passUnretained(kCGImagePropertyGIFDelayTime).toOpaque()), to: AnyObject.self)
}

delay = delayObject as! Double
return delay
}

class func gcdForPair(a: Int?, _ b: Int?) -> Int {
var a = a
var b = b
if b == nil || a == nil {
if b != nil {
return b!
} else if a != nil {
return a!
} else {
return 0
}
}

if a! < b! {
let c = a!
a = b!
b = c
}

var rest: Int
while true {
rest = a! % b!

if rest == 0 {
return b!
} else {
a = b!
b = rest
}
}
}

class func gcdForArray(array: Array<Int>) -> Int {
if array.isEmpty {
return 1
}

var gcd = array[0]

for val in array {
gcd = UIImage.gcdForPair(a: val, gcd)
}

return gcd
}

}