-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from hyperoslo/feature/os-x-support
Feature/os x support
- Loading branch information
Showing
18 changed files
with
580 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
github "krzyzanowskim/CryptoSwift" "0.4.1" | ||
github "hyperoslo/Cache" "36ef82487589ad6c91cfc66308ff0c799512b9d6" | ||
github "krzyzanowskim/CryptoSwift" "0.5.1" | ||
github "hyperoslo/Cache" "d6f0b013cbe9ede4b5fe5a8b615220abce0327d6" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>CFBundleDevelopmentRegion</key> | ||
<string>en</string> | ||
<key>CFBundleExecutable</key> | ||
<string>$(EXECUTABLE_NAME)</string> | ||
<key>CFBundleIdentifier</key> | ||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
<key>CFBundleInfoDictionaryVersion</key> | ||
<string>6.0</string> | ||
<key>CFBundleName</key> | ||
<string>$(PRODUCT_NAME)</string> | ||
<key>CFBundlePackageType</key> | ||
<string>FMWK</string> | ||
<key>CFBundleShortVersionString</key> | ||
<string>1.0</string> | ||
<key>CFBundleSignature</key> | ||
<string>????</string> | ||
<key>CFBundleVersion</key> | ||
<string>$(CURRENT_PROJECT_VERSION)</string> | ||
<key>NSHumanReadableCopyright</key> | ||
<string>Copyright © 2016 Hyper Interaktiv AS. All rights reserved.</string> | ||
<key>NSPrincipalClass</key> | ||
<string></string> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import Cocoa | ||
import Cache | ||
|
||
public struct Imaginary { | ||
|
||
public static var preConfigure: ((imageView: NSImageView) -> Void)? = { imageView in | ||
imageView.layer?.opacity = 0.0 | ||
} | ||
|
||
public static var transitionClosure: ((imageView: NSImageView, image: NSImage) -> Void) = { imageView, newImage in | ||
guard let oldImage = imageView.image else { | ||
imageView.image = newImage | ||
return | ||
} | ||
|
||
let animation = CABasicAnimation(keyPath: "contents") | ||
animation.duration = 0.25 | ||
animation.fromValue = oldImage.cgImage | ||
animation.toValue = newImage.cgImage | ||
imageView.layer?.addAnimation(animation, forKey: "transitionAnimation") | ||
imageView.image = newImage | ||
} | ||
|
||
public static var postConfigure: ((imageView: NSImageView) -> Void)? = { imageView in | ||
let animation = CABasicAnimation(keyPath: "opacity") | ||
animation.fromValue = imageView.layer?.opacity | ||
animation.toValue = 1.0 | ||
imageView.layer?.addAnimation(animation, forKey: "fadeAnimation") | ||
imageView.layer?.opacity = 1.0 | ||
} | ||
} | ||
|
||
public var imageCache: Cache<NSImage> { | ||
|
||
struct Static { | ||
static let config = Config( | ||
frontKind: .Memory, | ||
backKind: .Disk, | ||
expiry: .Date(NSDate().dateByAddingTimeInterval(60 * 60 * 24 * 3)), | ||
maxSize: 0, | ||
maxObjects: 10) | ||
|
||
static let cache = Cache<NSImage>(name: "Imaginary", config: config) | ||
} | ||
|
||
return Static.cache | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import Cocoa | ||
|
||
struct Decompressor { | ||
|
||
static func decompress(data: NSData, scale: CGFloat = 1) -> NSImage { | ||
guard let image = NSImage(data: data) else { return NSImage() } | ||
|
||
image.lockFocus() | ||
|
||
var imageRect: CGRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) | ||
let imageRef = image.CGImageForProposedRect(&imageRect, context: nil, hints: nil) | ||
|
||
if CGImageGetAlphaInfo(imageRef) != .None { return image } | ||
|
||
let colorSpaceRef = CGImageGetColorSpace(imageRef) | ||
let width = CGImageGetWidth(imageRef) | ||
let height = CGImageGetHeight(imageRef) | ||
let bytesPerPixel: Int = 4 | ||
let bytesPerRow: Int = bytesPerPixel * width | ||
let bitsPerComponent: Int = 8 | ||
|
||
let context = CGBitmapContextCreate(nil, | ||
width, | ||
height, | ||
bitsPerComponent, | ||
bytesPerRow, | ||
colorSpaceRef, | ||
CGBitmapInfo.ByteOrderDefault.rawValue) | ||
CGContextDrawImage(context, CGRectMake(0, 0, CGFloat(width), CGFloat(height)), imageRef) | ||
|
||
guard let imageRefWithoutAlpha = CGBitmapContextCreateImage(context) else { | ||
return NSImage() | ||
} | ||
let blendedImage = NSImage(CGImage: imageRefWithoutAlpha, size: NSSize(width: CGFloat(width), height: CGFloat(height))) | ||
|
||
return blendedImage | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import Cocoa | ||
import Foundation | ||
|
||
class Fetcher { | ||
|
||
enum Result { | ||
case Success(NSImage) | ||
case Failure(ErrorType) | ||
} | ||
|
||
enum Error: ErrorType { | ||
case InvalidResponse | ||
case InvalidStatusCode | ||
case InvalidData | ||
case InvalidContentLength | ||
case ConversionError | ||
} | ||
|
||
let URL: NSURL | ||
var task: NSURLSessionDataTask? | ||
var active = false | ||
|
||
var session: NSURLSession { | ||
return NSURLSession.sharedSession() | ||
} | ||
|
||
// MARK: - Initialization | ||
|
||
init(URL: NSURL) { | ||
self.URL = URL | ||
} | ||
|
||
// MARK: - Fetching | ||
|
||
func start(completion: (result: Result) -> Void) { | ||
active = true | ||
|
||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) { [weak self] in | ||
guard let weakSelf = self where weakSelf.active else { return } | ||
|
||
weakSelf.task = weakSelf.session.dataTaskWithURL(weakSelf.URL) { | ||
[weak self] data, response, error -> Void in | ||
|
||
guard let weakSelf = self where weakSelf.active else { return } | ||
|
||
if let error = error { | ||
weakSelf.complete { completion(result: .Failure(error)) } | ||
return | ||
} | ||
|
||
guard let httpResponse = response as? NSHTTPURLResponse else { | ||
weakSelf.complete { completion(result: .Failure(Error.InvalidResponse)) } | ||
return | ||
} | ||
|
||
guard httpResponse.statusCode == 200 else { | ||
weakSelf.complete { completion(result: .Failure(Error.InvalidStatusCode)) } | ||
return | ||
} | ||
|
||
guard let data = data where httpResponse.validateLength(data) else { | ||
weakSelf.complete { completion(result: .Failure(Error.InvalidContentLength)) } | ||
return | ||
} | ||
|
||
guard let image = NSImage.decode(data) else { | ||
weakSelf.complete { completion(result: .Failure(Error.ConversionError)) } | ||
return | ||
} | ||
|
||
if weakSelf.active { | ||
weakSelf.complete { completion(result: Result.Success(image)) } | ||
} | ||
} | ||
|
||
weakSelf.task?.resume() | ||
} | ||
} | ||
|
||
func cancel() { | ||
task?.cancel() | ||
active = false | ||
} | ||
|
||
func complete(closure: () -> Void) { | ||
active = false | ||
|
||
dispatch_async(dispatch_get_main_queue()) { | ||
closure() | ||
} | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import Cocoa | ||
|
||
extension NSImage { | ||
|
||
var cgImage: CGImage? { | ||
guard let data = TIFFRepresentation, | ||
source = CGImageSourceCreateWithData(data, nil), | ||
maskRef = CGImageSourceCreateImageAtIndex(source, 0, nil) | ||
else { | ||
return nil | ||
} | ||
|
||
return maskRef | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import Cocoa | ||
import Cache | ||
|
||
extension NSImage { | ||
|
||
public typealias CacheType = NSImage | ||
|
||
public static func decode(data: NSData) -> CacheType? { | ||
return Decompressor.decompress(data) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import Cocoa | ||
|
||
extension NSImageView { | ||
|
||
public func setImage(URL: NSURL?, placeholder: NSImage? = nil, completion: ((NSImage?) -> ())? = nil) { | ||
image = placeholder | ||
|
||
guard let URL = URL else { return } | ||
|
||
let key = URL.absoluteString | ||
|
||
if let fetcher = fetcher { | ||
fetcher.cancel() | ||
self.fetcher = nil | ||
} | ||
|
||
imageCache.object(key) { [weak self] object in | ||
guard let weakSelf = self else { return } | ||
|
||
if let image = object { | ||
dispatch_async(dispatch_get_main_queue()) { | ||
weakSelf.image = image | ||
completion?(image) | ||
} | ||
|
||
return | ||
} | ||
|
||
if placeholder == nil { | ||
Imaginary.preConfigure?(imageView: weakSelf) | ||
} | ||
|
||
weakSelf.fetcher = Fetcher(URL: URL) | ||
|
||
weakSelf.fetcher?.start { [weak self] result in | ||
guard let weakSelf = self else { return } | ||
|
||
switch result { | ||
case let .Success(image): | ||
Imaginary.transitionClosure(imageView: weakSelf, image: image) | ||
imageCache.add(key, object: image) | ||
completion?(image) | ||
default: | ||
break | ||
} | ||
Imaginary.postConfigure?(imageView: weakSelf) | ||
} | ||
} | ||
} | ||
|
||
var fetcher: Fetcher? { | ||
get { | ||
let wrapper = objc_getAssociatedObject(self, &Capsule.ObjectKey) as? Capsule | ||
let fetcher = wrapper?.value as? Fetcher | ||
return fetcher | ||
} | ||
set (fetcher) { | ||
var wrapper: Capsule? | ||
if let fetcher = fetcher { | ||
wrapper = Capsule(value: fetcher) | ||
} | ||
objc_setAssociatedObject(self, &Capsule.ObjectKey, | ||
wrapper, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.