Skip to content

Commit

Permalink
Merge pull request #14 from jpsim/xcode6p3b
Browse files Browse the repository at this point in the history
Fixes for Swift 1.2b and some refactoring
  • Loading branch information
jpsim committed Mar 2, 2015
2 parents 168f22b + 8eac8a3 commit b65513e
Show file tree
Hide file tree
Showing 17 changed files with 331 additions and 322 deletions.
12 changes: 6 additions & 6 deletions OSX/DeckRocket/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@
import Cocoa
import MultipeerConnectivity

class AppDelegate: NSObject, NSApplicationDelegate {
final class AppDelegate: NSObject, NSApplicationDelegate {

// MARK: Properties

let multipeerClient = MultipeerClient()
let menuView = MenuView()
private let menuView = MenuView()

// MARK: App

func applicationDidFinishLaunching(aNotification: NSNotification?) {
multipeerClient.onStateChange = {(state: MCSessionState) -> () in
var stateString = ""
func applicationDidFinishLaunching(aNotification: NSNotification) {
multipeerClient.onStateChange = { state in
let stateString: String
switch state {
case .NotConnected:
stateString = "Not Connected"
Expand All @@ -30,7 +30,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
stateString = "Connected"
}
dispatch_async(dispatch_get_main_queue()) {
self.menuView.menu!.itemAtIndex(0)!.title = stateString
self.menuView.menu?.itemAtIndex(0)?.title = stateString
}
}
}
Expand Down
26 changes: 16 additions & 10 deletions OSX/DeckRocket/HUDView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

import Cocoa

let hudWindow = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 300, height: 300),
private let hudWindow = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 300, height: 300),
styleMask: NSBorderlessWindowMask,
backing: .Buffered,
defer: false)

class HUDView: NSView {
final class HUDView: NSView {

override class func initialize() {
override static func initialize() {
hudWindow.backgroundColor = NSColor.clearColor()
hudWindow.opaque = false
hudWindow.makeKeyAndOrderFront(NSApp)
Expand All @@ -25,24 +25,30 @@ class HUDView: NSView {
DJProgressHUD.setBackgroundAlpha(0, disableActions: false)
}

class func show(string: String) {
DJProgressHUD.showProgress(1, withStatus: string, fromView: hudWindow.contentView as NSView)
static func show(string: String) {
if let windowView = hudWindow.contentView as? NSView {
DJProgressHUD.showProgress(1, withStatus: string, fromView: windowView)
}
let delay = 2 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) {
HUDView.dismiss()
}
}

class func showProgress(progress: CGFloat, string: String) {
DJProgressHUD.showProgress(progress, withStatus: string, fromView: hudWindow.contentView as NSView)
static func showProgress(progress: CGFloat, string: String) {
if let windowView = hudWindow.contentView as? NSView {
DJProgressHUD.showProgress(progress, withStatus: string, fromView: windowView)
}
}

class func showWithActivity(string: String) {
DJProgressHUD.showStatus(string, fromView: hudWindow.contentView as NSView)
static func showWithActivity(string: String) {
if let windowView = hudWindow.contentView as? NSView {
DJProgressHUD.showStatus(string, fromView: windowView)
}
}

class func dismiss() {
static func dismiss() {
DJProgressHUD.dismiss()
}
}
2 changes: 1 addition & 1 deletion OSX/DeckRocket/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.0.3</string>
<string>0.0.4</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
48 changes: 26 additions & 22 deletions OSX/DeckRocket/MenuView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@

import Cocoa

class MenuView: NSView, NSMenuDelegate {
var highlight = false
// FIXME: Use system-defined constant once accessible from Swift.
let NSVariableStatusItemLength: CGFloat = -1

// NSVariableStatusItemLength == -1
// Not using symbol because it doesn't link properly in Swift
let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)
final class MenuView: NSView, NSMenuDelegate {
private var highlight = false

private let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)

// MARK: Initializers

Expand All @@ -30,26 +31,28 @@ class MenuView: NSView, NSMenuDelegate {

// MARK: Menu

func setupMenu() {
private func setupMenu() {
let menu = NSMenu()
menu.addItemWithTitle("Not Connected", action: nil, keyEquivalent: "")
menu.itemAtIndex(0)!.enabled = false
menu.itemAtIndex(0)?.enabled = false
menu.addItemWithTitle("Quit DeckRocket", action: "quit", keyEquivalent: "")
self.menu = menu
self.menu!.delegate = self
self.menu?.delegate = self
}

override func mouseDown(theEvent: NSEvent) {
super.mouseDown(theEvent)
statusItem.popUpStatusItemMenu(menu!)
if let menu = menu {
statusItem.popUpStatusItemMenu(menu)
}
}

func menuWillOpen(menu: NSMenu!) {
func menuWillOpen(menu: NSMenu) {
highlight = true
needsDisplay = true
}

func menuDidClose(menu: NSMenu!) {
func menuDidClose(menu: NSMenu) {
highlight = false
needsDisplay = true
}
Expand All @@ -63,32 +66,33 @@ class MenuView: NSView, NSMenuDelegate {
// MARK: Dragging

override func draggingEntered(sender: NSDraggingInfo) -> NSDragOperation {
return NSDragOperation.Copy
return .Copy
}

override func performDragOperation(sender: NSDraggingInfo) -> Bool {
let pboard = sender.draggingPasteboard()
if contains(pboard.types as [NSString], NSFilenamesPboardType) {
let files = pboard.propertyListForType(NSFilenamesPboardType) as [String]
let file = files[0]
if validateFile(file) {
let appDelegate = NSApplication.sharedApplication().delegate as AppDelegate
appDelegate.multipeerClient.sendFile(file)
if contains((pboard.types as? [String]) ?? [], NSFilenamesPboardType) {
if let file = (pboard.propertyListForType(NSFilenamesPboardType) as? [String])?.first {
if validateFile(file) {
let appDelegate = NSApplication.sharedApplication().delegate as? AppDelegate
appDelegate?.multipeerClient.sendFile(file)
} else {
HUDView.show("Error!\nOnly PDF and Markdown files can be sent")
}
} else {
HUDView.show("Error!\nOnly PDF and Markdown files can be sent")
HUDView.show("Error!\nFile not found")
}
}
return true
}

func validateFile(filePath: NSString) -> Bool {
var allowedExtensions = [
private func validateFile(filePath: NSString) -> Bool {
let allowedExtensions = [
// Markdown
"markdown", "mdown", "mkdn", "md", "mkd", "mdwn", "mdtxt", "mdtext", "text",
// PDF
"pdf"
]

return contains(allowedExtensions, filePath.pathExtension.lowercaseString)
}
}
75 changes: 40 additions & 35 deletions OSX/DeckRocket/MultipeerClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,73 +10,76 @@ import Foundation
import MultipeerConnectivity

typealias stateChange = ((state: MCSessionState) -> ())?
typealias KVOContext = UInt8
var ProgressContext = KVOContext()
private typealias KVOContext = UInt8
private var progressContext = KVOContext()
private var lastDisplayTime = NSDate()

class MultipeerClient: NSObject, MCNearbyServiceAdvertiserDelegate, MCSessionDelegate {
final class MultipeerClient: NSObject, MCNearbyServiceAdvertiserDelegate, MCSessionDelegate {

// MARK: Properties

let localPeerID = MCPeerID(displayName: NSHost.currentHost().localizedName)
let advertiser: MCNearbyServiceAdvertiser?
var session: MCSession?
private let localPeerID = MCPeerID(displayName: NSHost.currentHost().localizedName)
private let advertiser: MCNearbyServiceAdvertiser?
private var session: MCSession?
private var pdfProgress: NSProgress?
var onStateChange: stateChange?
var pdfProgress: NSProgress?

// MARK: Lifecycle

override init() {
super.init()
advertiser = MCNearbyServiceAdvertiser(peer: localPeerID, discoveryInfo: nil, serviceType: "deckrocket")
advertiser!.delegate = self
advertiser!.startAdvertisingPeer()
super.init()
advertiser?.delegate = self
advertiser?.startAdvertisingPeer()
}

// MARK: Send File

func sendFile(filePath: String) {
let url = NSURL(fileURLWithPath: filePath)

if session == nil || session!.connectedPeers.count == 0 {
if session == nil || session!.connectedPeers.count == 0 { // Safe to force unwrap
HUDView.show("Error!\niPhone not connected")
return
}

let peer = session!.connectedPeers[0] as MCPeerID
pdfProgress = session!.sendResourceAtURL(url, withName: filePath.lastPathComponent, toPeer: peer) { error in
dispatch_async(dispatch_get_main_queue()) {
self.pdfProgress!.removeObserver(self, forKeyPath: "fractionCompleted", context: &ProgressContext)
if error != nil {
HUDView.show("Error!\n\(error.localizedDescription)")
} else {
HUDView.show("Success!")
if let peer = session?.connectedPeers[0] as? MCPeerID {
pdfProgress = session?.sendResourceAtURL(url, withName: filePath.lastPathComponent, toPeer: peer) { error in
dispatch_async(dispatch_get_main_queue()) {
self.pdfProgress?.removeObserver(self, forKeyPath: "fractionCompleted", context: &progressContext)
if let errorDescription = error?.localizedDescription {
HUDView.show("Error!\n\(errorDescription)")
} else {
HUDView.show("Success!")
}
}
}
pdfProgress?.addObserver(self, forKeyPath: "fractionCompleted", options: .New, context: &progressContext)
}
pdfProgress!.addObserver(self, forKeyPath: "fractionCompleted", options: .New, context: &ProgressContext)
}

// MARK: MCNearbyServiceAdvertiserDelegate

func advertiser(advertiser: MCNearbyServiceAdvertiser!, didReceiveInvitationFromPeer peerID: MCPeerID!, withContext context: NSData!, invitationHandler: ((Bool, MCSession!) -> Void)!) {
session = MCSession(peer: localPeerID, securityIdentity: nil, encryptionPreference: .None)
session!.delegate = self
invitationHandler(true, session!)
session?.delegate = self
invitationHandler(true, session)
}

// MARK: MCSessionDelegate

func session(session: MCSession!, peer peerID: MCPeerID!, didChangeState state: MCSessionState) {
if let block = onStateChange! {
block(state: state)
}
onStateChange??(state: state)
}

func session(session: MCSession!, didReceiveData data: NSData!, fromPeer peerID: MCPeerID!) {
let task = NSTask()
task.launchPath = NSBundle.mainBundle().pathForResource("deckrocket", ofType: "scpt")!
task.arguments = [NSString(data: data, encoding: NSUTF8StringEncoding)!]
task.launch()
if let launchPath = NSBundle.mainBundle().pathForResource("deckrocket", ofType: "scpt"),
argument = NSString(data: data, encoding: NSUTF8StringEncoding) {
let task = NSTask()
task.launchPath = launchPath
task.arguments = [argument]
task.launch()
}
}

func session(session: MCSession!, didReceiveStream stream: NSInputStream!, withName streamName: String!, fromPeer peerID: MCPeerID!) {
Expand All @@ -94,13 +97,15 @@ class MultipeerClient: NSObject, MCNearbyServiceAdvertiserDelegate, MCSessionDel
// MARK: KVO

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<()>) {
if context == &ProgressContext {
dispatch_async(dispatch_get_main_queue()) {
let progress = change[NSKeyValueChangeNewKey]! as CGFloat
HUDView.showProgress(progress, string: "Sending File to iPhone")
}
} else {
if context != &progressContext {
super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
} else if abs(lastDisplayTime.timeIntervalSinceNow) > 1/60 { // Update HUD at no more than 60fps
dispatch_sync(dispatch_get_main_queue()) {
if let progress = change[NSKeyValueChangeNewKey] as? CGFloat {
HUDView.showProgress(progress, string: "Sending File to iPhone")
lastDisplayTime = NSDate()
}
}
}
}
}
2 changes: 1 addition & 1 deletion OSX/DeckRocket/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@

import Cocoa

NSApplicationMain(C_ARGC, C_ARGV)
NSApplicationMain(Process.argc, Process.unsafeArgv)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

## Requirements

DeckRocket is built in Swift and relies on Multipeer Connectivity on both OSX and iOS. Therefore Xcode 6.1, OS X 10.10 and iOS 8 are all required to build, install and use DeckRocket.
DeckRocket is built in Swift and relies on Multipeer Connectivity on both OSX and iOS. Xcode 6.3b2, OS X 10.10 and iOS 8 are all required to build, install and use DeckRocket.

## Usage

Expand Down
12 changes: 5 additions & 7 deletions iOS/DeckRocket/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
final class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
var window: UIWindow? = UIWindow(frame: UIScreen.mainScreen().bounds)

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

self.window!.rootViewController = ViewController()
self.window!.makeKeyAndVisible()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
return true
}
}
4 changes: 2 additions & 2 deletions iOS/DeckRocket/Cell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import UIKit

class Cell: UICollectionViewCell {
final class Cell: UICollectionViewCell {
let imageView = UIImageView()

override init(frame: CGRect) {
Expand All @@ -22,6 +22,6 @@ class Cell: UICollectionViewCell {
}

override func layoutSubviews() {
imageView.frame = self.bounds
imageView.frame = bounds
}
}
6 changes: 4 additions & 2 deletions iOS/DeckRocket/CollectionViewLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@

import UIKit

class CollectionViewLayout: UICollectionViewFlowLayout {
final class CollectionViewLayout: UICollectionViewFlowLayout {

override init() {
super.init()
itemSize = UIApplication.sharedApplication().delegate!.window!!.bounds.size
if let windowSize = UIApplication.sharedApplication().delegate?.window??.bounds.size {
itemSize = windowSize
}
scrollDirection = .Horizontal
minimumInteritemSpacing = 0
minimumLineSpacing = 0
Expand Down
Loading

0 comments on commit b65513e

Please sign in to comment.