From 0256f5f5c1f67c825b159dd7b10abde6f80bacc1 Mon Sep 17 00:00:00 2001 From: David Schechter Date: Wed, 14 Sep 2016 11:10:05 -0700 Subject: [PATCH] Migrated to Swift 3 and ASDK 1.9.90 Changes according to @atainter comments Removed cocoapod junk and edited readme --- NMessenger.podspec | 4 +- Podfile | 2 +- README.md | 4 + nMessenger.xcodeproj/project.pbxproj | 123 ++++++- nMessenger/AppDelegate.swift | 12 +- .../AppIcon.appiconset/Contents.json | 20 ++ nMessenger/Info.plist | 5 + .../ImageBubbleConfiguration.swift | 18 +- .../SimpleBubbleConfiguration.swift | 14 +- .../StandardBubbleConfiguration.swift | 14 +- .../Source/MessageNodes/Bubbles/Bubble.swift | 22 +- .../MessageNodes/Bubbles/DefaultBubble.swift | 47 +-- .../MessageNodes/Bubbles/ImageBubble.swift | 46 +-- .../MessageNodes/Bubbles/SimpleBubble.swift | 36 ++- .../MessageNodes/Bubbles/StackedBubble.swift | 49 +-- .../CollectionViewContentNode.swift | 64 ++-- .../CustomContentCellNode.swift | 6 +- .../ContentNodes/ContentNode.swift | 44 ++- .../CustomContentNode.swift | 30 +- .../ImageContent/ImageContentNode.swift | 36 +-- .../NetworkImageContentNode.swift | 42 +-- .../TextContent/TextContentNode.swift | 132 ++++---- .../TypingIndicatorContent.swift | 14 +- .../GeneralMessengerCell.swift | 12 +- .../Indicators/HeadLoadingIndicator.swift | 32 +- .../Indicators/MessageSentIndicator.swift | 24 +- .../MessageCell/MessageCellProtocol.swift | 4 +- .../MessageCell/MessageGroup.swift | 205 ++++++------ .../MessageCell/MessageNode.swift | 76 ++--- .../Components/CameraViewController.swift | 253 ++++++++------- .../InputBarView/InputBarView.swift | 12 +- .../InputBarView/NMessengerBarView.swift | 112 +++---- .../Messenger/Components/NMessenger.swift | 304 +++++++++--------- .../Messenger/NMessengerViewController.swift | 164 +++++----- .../Utilities/ModalAlertUtilities.swift | 62 ++-- .../Source/Utilities/UIColor+N1Colors.swift | 4 +- .../Source/Utilities/UIFont+N1Fonts.swift | 26 +- .../Messenger/NMessengerTests.swift | 48 +-- .../UI Components/Chat/BubbleTests.swift | 12 +- .../Chat/CollectionViewContentNodeTests.swift | 10 +- .../Chat/HeadLoadingIndicatorTests.swift | 4 +- .../Chat/NetworkImageContentNodeTests.swift | 6 +- nMessengerTests/nMessengerTests.swift | 2 +- 43 files changed, 1192 insertions(+), 964 deletions(-) diff --git a/NMessenger.podspec b/NMessenger.podspec index d37d0d7..85e57c1 100644 --- a/NMessenger.podspec +++ b/NMessenger.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "NMessenger" - s.version = "1.0.76" + s.version = "1.0.77" s.summary = "A fast, lightweight messenger component built on AsyncDisplaykit and written in Swift" # This description is used to generate tags and improve search results. @@ -133,5 +133,5 @@ NMessenger is a fast, lightweight messenger component built on AsyncDisplaykit a s.requires_arc = true # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } - s.dependency "AsyncDisplayKit", "1.9.80" + s.dependency "AsyncDisplayKit", "1.9.90" end diff --git a/Podfile b/Podfile index 841a210..768b5f4 100644 --- a/Podfile +++ b/Podfile @@ -6,7 +6,7 @@ target 'nMessenger' do use_frameworks! # Pods for nMessenger - pod 'AsyncDisplayKit', '1.9.80' + pod 'AsyncDisplayKit', ‘1.9.90' target 'nMessengerTests' do inherit! :search_paths diff --git a/README.md b/README.md index a1fc4fd..569af2a 100755 --- a/README.md +++ b/README.md @@ -37,6 +37,10 @@ pod 'NMessenger' ``` ## Notes +###For iOS 10 Support +Add `NSPhotoLibraryUsageDescription` and `NSCameraUsageDescription` to your App Info.plist to specify the reason for accessing photo library and camera. See [Cocoa Keys](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html) for more details. + +###Landscape Mode - **Landscape mode is not currently supported.** While it may be supported in a future release, we have disabled device rotation for `NMessengerViewController` to prevent issues. ## Getting Started diff --git a/nMessenger.xcodeproj/project.pbxproj b/nMessenger.xcodeproj/project.pbxproj index 03e0965..354c136 100755 --- a/nMessenger.xcodeproj/project.pbxproj +++ b/nMessenger.xcodeproj/project.pbxproj @@ -466,6 +466,13 @@ path = Extensions; sourceTree = ""; }; + 7E0C8FBB9D65E94C7CDC7F2A /* Pods */ = { + isa = PBXGroup; + children = ( + ); + name = Pods; + sourceTree = ""; + }; CEEA4FEAB14A1E9BACDB8B3A /* Frameworks */ = { isa = PBXGroup; children = ( @@ -481,6 +488,7 @@ F1418D051D380B2400C404B5 /* nMessengerUITests */, F1418CE41D380B2400C404B5 /* Products */, CEEA4FEAB14A1E9BACDB8B3A /* Frameworks */, + 7E0C8FBB9D65E94C7CDC7F2A /* Pods */, ); sourceTree = ""; }; @@ -906,9 +914,12 @@ isa = PBXNativeTarget; buildConfigurationList = F1418D0E1D380B2400C404B5 /* Build configuration list for PBXNativeTarget "nMessengerTests" */; buildPhases = ( + A1EAC93D3E60EE9287D5A1A1 /* [CP] Check Pods Manifest.lock */, F1418CF31D380B2400C404B5 /* Sources */, F1418CF41D380B2400C404B5 /* Frameworks */, F1418CF51D380B2400C404B5 /* Resources */, + C0C629968B1A2B229A2FC68A /* [CP] Embed Pods Frameworks */, + B63E1D299EF994DC6556DA08 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -924,9 +935,12 @@ isa = PBXNativeTarget; buildConfigurationList = F1418D111D380B2400C404B5 /* Build configuration list for PBXNativeTarget "nMessengerUITests" */; buildPhases = ( + D85CE90B54825D807BA9D883 /* [CP] Check Pods Manifest.lock */, F1418CFE1D380B2400C404B5 /* Sources */, F1418CFF1D380B2400C404B5 /* Frameworks */, F1418D001D380B2400C404B5 /* Resources */, + F7B47B6A4B98158750DAB112 /* [CP] Embed Pods Frameworks */, + 92EE1EB1707ECEA825593FBA /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -945,18 +959,21 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0730; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Ebay Inc."; TargetAttributes = { F1418CE21D380B2400C404B5 = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; }; F1418CF61D380B2400C404B5 = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; TestTargetID = F1418CE21D380B2400C404B5; }; F1418D011D380B2400C404B5 = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; TestTargetID = F1418CE21D380B2400C404B5; }; }; @@ -1141,6 +1158,99 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 92EE1EB1707ECEA825593FBA /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-nMessengerUITests/Pods-nMessengerUITests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + A1EAC93D3E60EE9287D5A1A1 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + B63E1D299EF994DC6556DA08 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-nMessengerTests/Pods-nMessengerTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + C0C629968B1A2B229A2FC68A /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-nMessengerTests/Pods-nMessengerTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D85CE90B54825D807BA9D883 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + F7B47B6A4B98158750DAB112 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-nMessengerUITests/Pods-nMessengerUITests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ F1418CDF1D380B2400C404B5 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -1259,8 +1369,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -1305,8 +1417,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -1325,6 +1439,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -1340,6 +1455,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ebay.nMessenger; PRODUCT_NAME = nMessenger; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -1353,6 +1469,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ebay.nMessenger; PRODUCT_NAME = nMessenger; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -1364,6 +1481,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ebay.nMessengerTests; PRODUCT_NAME = nMessengerTests; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/nMessenger.app/nMessenger"; }; name = Debug; @@ -1376,6 +1494,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ebay.nMessengerTests; PRODUCT_NAME = nMessengerTests; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/nMessenger.app/nMessenger"; }; name = Release; @@ -1387,6 +1506,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ebay.nMessengerUITests; PRODUCT_NAME = nMessengerUITests; + SWIFT_VERSION = 3.0; TEST_TARGET_NAME = nMessenger; }; name = Debug; @@ -1398,6 +1518,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ebay.nMessengerUITests; PRODUCT_NAME = nMessengerUITests; + SWIFT_VERSION = 3.0; TEST_TARGET_NAME = nMessenger; }; name = Release; diff --git a/nMessenger/AppDelegate.swift b/nMessenger/AppDelegate.swift index 5568336..d4d888f 100755 --- a/nMessenger/AppDelegate.swift +++ b/nMessenger/AppDelegate.swift @@ -16,30 +16,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/nMessenger/Assets.xcassets/AppIcon.appiconset/Contents.json b/nMessenger/Assets.xcassets/AppIcon.appiconset/Contents.json index eeea76c..1d060ed 100755 --- a/nMessenger/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/nMessenger/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -30,6 +40,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", diff --git a/nMessenger/Info.plist b/nMessenger/Info.plist index 40c6215..056b5d7 100755 --- a/nMessenger/Info.plist +++ b/nMessenger/Info.plist @@ -43,5 +43,10 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + NSPhotoLibraryUsageDescription + $(PRODUCT_NAME) wants acceess to Photos + NSCameraUsageDescription + $(PRODUCT_NAME) wants acceess to Camera + diff --git a/nMessenger/Source/MessageNodes/BubbleConfiguration/ImageBubbleConfiguration.swift b/nMessenger/Source/MessageNodes/BubbleConfiguration/ImageBubbleConfiguration.swift index 817e927..3bdb668 100755 --- a/nMessenger/Source/MessageNodes/BubbleConfiguration/ImageBubbleConfiguration.swift +++ b/nMessenger/Source/MessageNodes/BubbleConfiguration/ImageBubbleConfiguration.swift @@ -12,37 +12,37 @@ import Foundation import UIKit /** Uses a simple bubble as primary and a simple bubble as secondary. Incoming color is pale grey and outgoing is mid grey */ -public class ImageBubbleConfiguration: BubbleConfigurationProtocol { +open class ImageBubbleConfiguration: BubbleConfigurationProtocol { - public var isMasked = false + open var isMasked = false public init() {} - public func getIncomingColor() -> UIColor + open func getIncomingColor() -> UIColor { return UIColor.n1PaleGreyColor() } - public func getOutgoingColor() -> UIColor + open func getOutgoingColor() -> UIColor { return UIColor.n1ActionBlueColor() } - public func getBubble() -> Bubble + open func getBubble() -> Bubble { let newBubble = ImageBubble() - newBubble.bubbleImage = UIImage(named: "MessageBubble", inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil) + newBubble.bubbleImage = UIImage(named: "MessageBubble", in: Bundle(for: NMessengerViewController.self), compatibleWith: nil) newBubble.cutInsets = UIEdgeInsetsMake(29, 32, 25, 43) newBubble.hasLayerMask = isMasked return newBubble } - public func getSecondaryBubble() -> Bubble + open func getSecondaryBubble() -> Bubble { let newBubble = ImageBubble() - newBubble.bubbleImage = UIImage(named: "MessageBubble", inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil) + newBubble.bubbleImage = UIImage(named: "MessageBubble", in: Bundle(for: NMessengerViewController.self), compatibleWith: nil) newBubble.cutInsets = UIEdgeInsetsMake(29, 32, 25, 43) newBubble.hasLayerMask = isMasked return newBubble } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/BubbleConfiguration/SimpleBubbleConfiguration.swift b/nMessenger/Source/MessageNodes/BubbleConfiguration/SimpleBubbleConfiguration.swift index 8eee34e..f636fff 100755 --- a/nMessenger/Source/MessageNodes/BubbleConfiguration/SimpleBubbleConfiguration.swift +++ b/nMessenger/Source/MessageNodes/BubbleConfiguration/SimpleBubbleConfiguration.swift @@ -12,33 +12,33 @@ import Foundation import UIKit /** Uses a simple bubble as primary and a simple bubble as secondary. Incoming color is pale grey and outgoing is mid grey */ -public class SimpleBubbleConfiguration: BubbleConfigurationProtocol { +open class SimpleBubbleConfiguration: BubbleConfigurationProtocol { - public var isMasked = false + open var isMasked = false public init() {} - public func getIncomingColor() -> UIColor + open func getIncomingColor() -> UIColor { return UIColor.n1PaleGreyColor() } - public func getOutgoingColor() -> UIColor + open func getOutgoingColor() -> UIColor { return UIColor.n1MidGreyColor() } - public func getBubble() -> Bubble + open func getBubble() -> Bubble { let newBubble = SimpleBubble() newBubble.hasLayerMask = isMasked return newBubble } - public func getSecondaryBubble() -> Bubble + open func getSecondaryBubble() -> Bubble { let newBubble = SimpleBubble() newBubble.hasLayerMask = isMasked return newBubble } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/BubbleConfiguration/StandardBubbleConfiguration.swift b/nMessenger/Source/MessageNodes/BubbleConfiguration/StandardBubbleConfiguration.swift index e9d4143..021ba24 100755 --- a/nMessenger/Source/MessageNodes/BubbleConfiguration/StandardBubbleConfiguration.swift +++ b/nMessenger/Source/MessageNodes/BubbleConfiguration/StandardBubbleConfiguration.swift @@ -12,33 +12,33 @@ import Foundation import UIKit /** Uses a default bubble as primary and a stacked bubble as secondary. Incoming color is pale grey and outgoing is blue */ -public class StandardBubbleConfiguration: BubbleConfigurationProtocol { +open class StandardBubbleConfiguration: BubbleConfigurationProtocol { - public var isMasked = false + open var isMasked = false public init() {} - public func getIncomingColor() -> UIColor + open func getIncomingColor() -> UIColor { return UIColor.n1PaleGreyColor() } - public func getOutgoingColor() -> UIColor + open func getOutgoingColor() -> UIColor { return UIColor.n1ActionBlueColor() } - public func getBubble() -> Bubble + open func getBubble() -> Bubble { let newBubble = DefaultBubble() newBubble.hasLayerMask = isMasked return newBubble } - public func getSecondaryBubble() -> Bubble + open func getSecondaryBubble() -> Bubble { let newBubble = StackedBubble() newBubble.hasLayerMask = isMasked return newBubble } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/Bubbles/Bubble.swift b/nMessenger/Source/MessageNodes/Bubbles/Bubble.swift index 608c2c3..2f7031b 100755 --- a/nMessenger/Source/MessageNodes/Bubbles/Bubble.swift +++ b/nMessenger/Source/MessageNodes/Bubbles/Bubble.swift @@ -16,25 +16,25 @@ import AsyncDisplayKit /** 'Abstract' Bubble class. Subclass for creating a custom bubble */ -public class Bubble { +open class Bubble { // MARK: Public Parameters - public var bubbleColor : UIColor = UIColor.n1PaleGreyColor() + open var bubbleColor : UIColor = UIColor.n1PaleGreyColor() /** When this is set, the layer mask will mask the ContentNode.*/ - public var hasLayerMask = false + open var hasLayerMask = false /** A layer for the bubble. Make sure this property is first accessed on the main thread. */ - public lazy var layer: CAShapeLayer = CAShapeLayer() + open lazy var layer: CAShapeLayer = CAShapeLayer() /** A layer that holds a mask which is the same shape as the bubble. This can be used to mask anything in the ContentNode to the same shape as the bubble. */ - public lazy var maskLayer: CAShapeLayer = CAShapeLayer() + open lazy var maskLayer: CAShapeLayer = CAShapeLayer() /** Bounds of the bubble*/ - public var calculatedBounds = CGRectZero + open var calculatedBounds = CGRect.zero // MARK: Initialisers public init() {} @@ -44,7 +44,7 @@ public class Bubble { Sizes the layer accordingly. This function should **always** be thread safe. -parameter bounds: The bounds of the content */ - public func sizeToBounds(bounds: CGRect) { + open func sizeToBounds(_ bounds: CGRect) { self.calculatedBounds = bounds } @@ -52,12 +52,12 @@ public class Bubble { /** This function should be called on the main thread. It makes creates the layer with the calculated values from *sizeToBounds* */ - public func createLayer() { + open func createLayer() { self.layer.shouldRasterize = true - self.layer.rasterizationScale = UIScreen.mainScreen().scale + self.layer.rasterizationScale = UIScreen.main.scale self.maskLayer.shouldRasterize = true - self.maskLayer.rasterizationScale = UIScreen.mainScreen().scale + self.maskLayer.rasterizationScale = UIScreen.main.scale } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/Bubbles/DefaultBubble.swift b/nMessenger/Source/MessageNodes/Bubbles/DefaultBubble.swift index f5a7d44..75af9e5 100755 --- a/nMessenger/Source/MessageNodes/Bubbles/DefaultBubble.swift +++ b/nMessenger/Source/MessageNodes/Bubbles/DefaultBubble.swift @@ -15,18 +15,18 @@ import UIKit /** Default bubble class is standard with our message configuration. It has three rounded corners and one square corner closest to the avatar. */ -public class DefaultBubble: Bubble { +open class DefaultBubble: Bubble { //MARK: Public Variables /** Radius of the corners for the bubble. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var radius : CGFloat = 16 + open var radius : CGFloat = 16 /** Should be less or equal to the *radius* property. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var borderWidth : CGFloat = 0 //TODO: + open var borderWidth : CGFloat = 0 //TODO: /** The color of the border around the bubble. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var bubbleBorderColor : UIColor = UIColor.clearColor() + open var bubbleBorderColor : UIColor = UIColor.clear /** Path used to cutout the bubble*/ - public private(set) var path: CGMutablePath = CGPathCreateMutable() + open fileprivate(set) var path: CGMutablePath = CGMutablePath() // MARK: Initialisers @@ -43,10 +43,10 @@ public class DefaultBubble: Bubble { Overriding sizeToBounds from super class -parameter bounds: The bounds of the content */ - public override func sizeToBounds(bounds: CGRect) { + open override func sizeToBounds(_ bounds: CGRect) { super.sizeToBounds(bounds) - var rect = CGRectZero + var rect = CGRect.zero var radius2: CGFloat = 0 if bounds.width < 2*radius || bounds.height < 2*radius { //if the rect calculation yeilds a negative result @@ -55,40 +55,45 @@ public class DefaultBubble: Bubble { let newRadius = newRadiusW>newRadiusH ? newRadiusH : newRadiusW - rect = CGRectMake(newRadius, newRadius, bounds.width - 2*newRadius, bounds.height - 2*newRadius) + rect = CGRect(x: newRadius, y: newRadius, width: bounds.width - 2*newRadius, height: bounds.height - 2*newRadius) radius2 = newRadius - borderWidth / 2 } else { - rect = CGRectMake(radius, radius, bounds.width - 2*radius, bounds.height - 2*radius) + rect = CGRect(x: radius, y: radius, width: bounds.width - 2*radius, height: bounds.height - 2*radius) radius2 = radius - borderWidth / 2 } - path = CGPathCreateMutable() - - CGPathAddArc(path, nil, rect.maxX, rect.minY, radius2, CGFloat(-M_PI_2), 0, false) - CGPathAddLineToPoint(path, nil, rect.maxX + radius2, rect.maxY + radius2) - CGPathAddArc(path, nil, rect.minX, rect.maxY, radius2, CGFloat(M_PI_2), CGFloat(M_PI), false) - CGPathAddArc(path, nil, rect.minX, rect.minY, radius2, CGFloat(M_PI), CGFloat(-M_PI_2), false) - CGPathCloseSubpath(path) + path = CGMutablePath() + + path.addArc(center: CGPoint(x: rect.maxX, y: rect.minY), radius: radius2, startAngle: CGFloat(-M_PI_2), endAngle: 0, clockwise: false) + path.addLine(to: CGPoint(x: rect.maxX + radius2, y: rect.maxY + radius2)) + path.addArc(center: CGPoint(x: rect.minX, y: rect.maxY), radius: radius2, startAngle: CGFloat(M_PI_2), endAngle: CGFloat(M_PI), clockwise: false) + path.addArc(center: CGPoint(x: rect.minX, y: rect.minY), radius: radius2, startAngle: CGFloat(M_PI), endAngle: CGFloat(-M_PI_2), clockwise: false) + + //CGPathAddArc(path, nil, rect.maxX, rect.minY, radius2, CGFloat(-M_PI_2), 0, false) + //CGPathAddLineToPoint(path, nil, rect.maxX + radius2, rect.maxY + radius2) + //CGPathAddArc(path, nil, rect.minX, rect.maxY, radius2, CGFloat(M_PI_2), CGFloat(M_PI), false) + //CGPathAddArc(path, nil, rect.minX, rect.minY, radius2, CGFloat(M_PI), CGFloat(-M_PI_2), false) + path.closeSubpath() } /** Overriding createLayer from super class */ - public override func createLayer() { + open override func createLayer() { super.createLayer() CATransaction.begin() CATransaction.setDisableActions(true) self.layer.path = path - self.layer.fillColor = self.bubbleColor.CGColor - self.layer.strokeColor = self.bubbleBorderColor.CGColor + self.layer.fillColor = self.bubbleColor.cgColor + self.layer.strokeColor = self.bubbleBorderColor.cgColor self.layer.lineWidth = self.borderWidth self.layer.position = CGPoint.zero - self.maskLayer.fillColor = UIColor.blackColor().CGColor + self.maskLayer.fillColor = UIColor.black.cgColor self.maskLayer.path = path self.maskLayer.position = CGPoint.zero CATransaction.commit() } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/Bubbles/ImageBubble.swift b/nMessenger/Source/MessageNodes/Bubbles/ImageBubble.swift index 64457f8..23cc214 100755 --- a/nMessenger/Source/MessageNodes/Bubbles/ImageBubble.swift +++ b/nMessenger/Source/MessageNodes/Bubbles/ImageBubble.swift @@ -16,13 +16,13 @@ import UIKit Image as background for messages in NMessenger Uses 9-Patch logic to resize image to appropriate size. */ -public class ImageBubble : Bubble { +open class ImageBubble : Bubble { // MARK: Public variables /** Image 9-Patch used for bubble. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var bubbleImage: UIImage? + open var bubbleImage: UIImage? /** Image 9-Patch cut insets. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var cutInsets: UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0) + open var cutInsets: UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0) // MARK: Initialisers @@ -41,7 +41,7 @@ public class ImageBubble : Bubble { Overriding sizeToBounds from super class -parameter bounds: The bounds of the content */ - public override func sizeToBounds(bounds: CGRect) { + open override func sizeToBounds(_ bounds: CGRect) { super.sizeToBounds(bounds) } @@ -49,17 +49,17 @@ public class ImageBubble : Bubble { /** Overriding createLayer from super class */ - public override func createLayer() { + open override func createLayer() { super.createLayer() if let image = bubbleImage { UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale); let context = UIGraphicsGetCurrentContext(); self.bubbleColor.setFill() - CGContextTranslateCTM(context, 0, image.size.height); - CGContextScaleCTM(context, 1.0, -1.0); - CGContextClipToMask(context, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage); - CGContextFillRect(context, CGRectMake(0, 0, image.size.width, image.size.height)); + context?.translateBy(x: 0, y: image.size.height); + context?.scaleBy(x: 1.0, y: -1.0); + context?.clip(to: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height), mask: image.cgImage!); + context?.fill(CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)); var coloredImg = UIGraphicsGetImageFromCurrentImageContext(); @@ -67,25 +67,25 @@ public class ImageBubble : Bubble { let insets = self.cutInsets - coloredImg = coloredImg.resizableImageWithCapInsets(insets, resizingMode: .Stretch) + coloredImg = coloredImg?.resizableImage(withCapInsets: insets, resizingMode: .stretch) - self.layer.contents = coloredImg.CGImage - self.layer.position = CGPointZero + self.layer.contents = coloredImg?.cgImage + self.layer.position = CGPoint.zero self.layer.frame = CGRect(x: 0, y: 0, width: self.calculatedBounds.width, height: self.calculatedBounds.height) - self.layer.contentsCenter = CGRectMake(insets.left/coloredImg.size.width, - insets.top/coloredImg.size.height, - 1.0/coloredImg.size.width, - 1.0/coloredImg.size.height); + self.layer.contentsCenter = CGRect(x: insets.left/(coloredImg?.size.width)!, + y: insets.top/(coloredImg?.size.height)!, + width: 1.0/(coloredImg?.size.width)!, + height: 1.0/(coloredImg?.size.height)!); - self.maskLayer.contents = coloredImg.CGImage - self.maskLayer.position = CGPointZero + self.maskLayer.contents = coloredImg?.cgImage + self.maskLayer.position = CGPoint.zero self.maskLayer.frame = CGRect(x: 0, y: 0, width: self.calculatedBounds.width, height: self.calculatedBounds.height) - self.maskLayer.contentsCenter = CGRectMake(insets.left/coloredImg.size.width, - insets.top/coloredImg.size.height, - 1.0/coloredImg.size.width, - 1.0/coloredImg.size.height); + self.maskLayer.contentsCenter = CGRect(x: insets.left/(coloredImg?.size.width)!, + y: insets.top/(coloredImg?.size.height)!, + width: 1.0/(coloredImg?.size.width)!, + height: 1.0/(coloredImg?.size.height)!); } } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/Bubbles/SimpleBubble.swift b/nMessenger/Source/MessageNodes/Bubbles/SimpleBubble.swift index 25f4c0b..c56849e 100755 --- a/nMessenger/Source/MessageNodes/Bubbles/SimpleBubble.swift +++ b/nMessenger/Source/MessageNodes/Bubbles/SimpleBubble.swift @@ -15,13 +15,13 @@ import UIKit /** Simple bubble with no layer effects which is the bounds of the content it holds */ -public class SimpleBubble: Bubble { +open class SimpleBubble: Bubble { //MARK: Public Variables /** The color of the border around the bubble. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var bubbleBorderColor : UIColor = UIColor.clearColor() + open var bubbleBorderColor : UIColor = UIColor.clear /** Path used to cutout the bubble*/ - public private(set) var path: CGMutablePath = CGPathCreateMutable() + open fileprivate(set) var path: CGMutablePath = CGMutablePath() public override init() { super.init() @@ -33,37 +33,43 @@ public class SimpleBubble: Bubble { Overriding sizeToBounds from super class -parameter bounds: The bounds of the content */ - public override func sizeToBounds(bounds: CGRect) { + open override func sizeToBounds(_ bounds: CGRect) { super.sizeToBounds(bounds) let rect = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height) - path = CGPathCreateMutable() + path = CGMutablePath() - CGPathMoveToPoint(path, nil, rect.minX, rect.minY) - CGPathAddLineToPoint(path, nil, rect.maxX, rect.minY) - CGPathAddLineToPoint(path, nil, rect.maxX, rect.maxY) - CGPathAddLineToPoint(path, nil, rect.minX, rect.maxY) - CGPathCloseSubpath(path) + path.move(to: CGPoint(x: rect.minX, y: rect.minY)) + path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY)) + path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) + path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY)) + + // CGPathMoveToPoint(path, nil, rect.minX, rect.minY) + // CGPathAddLineToPoint(path, nil, rect.maxX, rect.minY) + // CGPathAddLineToPoint(path, nil, rect.maxX, rect.maxY) + // CGPathAddLineToPoint(path, nil, rect.minX, rect.maxY) + + path.closeSubpath() } /** Overriding createLayer from super class */ - public override func createLayer() { + open override func createLayer() { super.createLayer() CATransaction.begin() CATransaction.setDisableActions(true) self.layer.path = path - self.layer.fillColor = self.bubbleColor.CGColor - self.layer.strokeColor = self.bubbleBorderColor.CGColor + self.layer.fillColor = self.bubbleColor.cgColor + self.layer.strokeColor = self.bubbleBorderColor.cgColor self.layer.position = CGPoint.zero - self.maskLayer.fillColor = UIColor.blackColor().CGColor + self.maskLayer.fillColor = UIColor.black.cgColor self.maskLayer.path = path self.maskLayer.position = CGPoint.zero CATransaction.commit() } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/Bubbles/StackedBubble.swift b/nMessenger/Source/MessageNodes/Bubbles/StackedBubble.swift index fa60086..97c8ee2 100755 --- a/nMessenger/Source/MessageNodes/Bubbles/StackedBubble.swift +++ b/nMessenger/Source/MessageNodes/Bubbles/StackedBubble.swift @@ -15,18 +15,18 @@ import UIKit /** Bubble when stacked for succeeding messages. The two outmost corners are rounded. */ -public class StackedBubble: Bubble { +open class StackedBubble: Bubble { //MARK: Public Variables /** Radius of the corners for the bubble. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var radius : CGFloat = 16 + open var radius : CGFloat = 16 /** Should be less or equal to the *radius* property. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var borderWidth : CGFloat = 0 + open var borderWidth : CGFloat = 0 /** The color of the border around the bubble. When this is set, you will need to call setNeedsLayout on your message for changes to take effect if the bubble has already been drawn*/ - public var bubbleBorderColor : UIColor = UIColor.clearColor() + open var bubbleBorderColor : UIColor = UIColor.clear /** Path used to cutout the bubble*/ - public private(set) var path: CGMutablePath = CGPathCreateMutable() + open fileprivate(set) var path: CGMutablePath = CGMutablePath() public override init() { super.init() @@ -38,9 +38,9 @@ public class StackedBubble: Bubble { Overriding sizeToBounds from super class -parameter bounds: The bounds of the content */ - public override func sizeToBounds(bounds: CGRect) { + open override func sizeToBounds(_ bounds: CGRect) { super.sizeToBounds(bounds) - var rect = CGRectZero + var rect = CGRect.zero var radius2: CGFloat = 0 if bounds.width < 2*radius || bounds.height < 2*radius { //if the rect calculation yeilds a negative result @@ -49,42 +49,49 @@ public class StackedBubble: Bubble { let newRadius = newRadiusW>newRadiusH ? newRadiusH : newRadiusW - rect = CGRectMake(newRadius, newRadius, bounds.width - 2*newRadius, bounds.height - 2*newRadius) + rect = CGRect(x: newRadius, y: newRadius, width: bounds.width - 2*newRadius, height: bounds.height - 2*newRadius) radius2 = newRadius - borderWidth / 2 } else { - rect = CGRectMake(radius, radius, bounds.width - 2*radius, bounds.height - 2*radius) + rect = CGRect(x: radius, y: radius, width: bounds.width - 2*radius, height: bounds.height - 2*radius) radius2 = radius - borderWidth / 2 } - self.path = CGPathCreateMutable(); + self.path = CGMutablePath(); - CGPathMoveToPoint(path, nil, rect.minX, rect.minY - radius2) - CGPathAddLineToPoint(path, nil, rect.maxX + radius2, rect.minY - radius2) - CGPathAddLineToPoint(path, nil, rect.maxX + radius2, rect.maxY + radius2) - CGPathAddArc(path, nil, rect.minX, rect.maxY, radius2, CGFloat(M_PI_2), CGFloat(M_PI), false) - CGPathAddArc(path, nil, rect.minX, rect.minY, radius2, CGFloat(M_PI), CGFloat(-M_PI_2), false) - CGPathCloseSubpath(path) + + path.move(to: CGPoint(x: rect.minX, y: rect.minY - radius2)) + path.addLine(to: CGPoint(x: rect.maxX + radius2, y: rect.minY - radius2)) + path.addLine(to: CGPoint(x: rect.maxX + radius2, y: rect.maxY + radius2)) + path.addArc(center: CGPoint(x: rect.minX, y: rect.maxY), radius: radius2, startAngle: CGFloat(M_PI_2), endAngle: CGFloat(M_PI), clockwise: false) + path.addArc(center: CGPoint(x: rect.minX, y: rect.minY), radius: radius2, startAngle: CGFloat(M_PI_2), endAngle: CGFloat(-M_PI_2), clockwise: false) + + //CGPathMoveToPoint(path, nil, rect.minX, rect.minY - radius2) + //CGPathAddLineToPoint(path, nil, rect.maxX + radius2, rect.minY - radius2) + //CGPathAddLineToPoint(path, nil, rect.maxX + radius2, rect.maxY + radius2) + //CGPathAddArc(path, nil, rect.minX, rect.maxY, radius2, CGFloat(M_PI_2), CGFloat(M_PI), false) + //CGPathAddArc(path, nil, rect.minX, rect.minY, radius2, CGFloat(M_PI), CGFloat(-M_PI_2), false) + path.closeSubpath() } /** Overriding createLayer from super class */ - public override func createLayer() { + open override func createLayer() { super.createLayer() CATransaction.begin() CATransaction.setDisableActions(true) self.layer.path = path - self.layer.fillColor = self.bubbleColor.CGColor - self.layer.strokeColor = self.bubbleBorderColor.CGColor + self.layer.fillColor = self.bubbleColor.cgColor + self.layer.strokeColor = self.bubbleBorderColor.cgColor self.layer.lineWidth = self.borderWidth self.layer.position = CGPoint.zero - self.maskLayer.fillColor = UIColor.blackColor().CGColor + self.maskLayer.fillColor = UIColor.black.cgColor self.maskLayer.path = path self.maskLayer.position = CGPoint.zero CATransaction.commit() } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/ContentNodes/CollectionViewContent/CollectionViewContentNode.swift b/nMessenger/Source/MessageNodes/ContentNodes/CollectionViewContent/CollectionViewContentNode.swift index 5e3e567..d457a15 100755 --- a/nMessenger/Source/MessageNodes/ContentNodes/CollectionViewContent/CollectionViewContentNode.swift +++ b/nMessenger/Source/MessageNodes/ContentNodes/CollectionViewContent/CollectionViewContentNode.swift @@ -17,10 +17,10 @@ import AsyncDisplayKit Define content that is a collection view. The collection view can have 1 row or multiple row. Cells can be either views or nodes. */ -public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASCollectionDataSource, UICollectionViewDelegateFlowLayout { +open class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASCollectionDataSource, UICollectionViewDelegateFlowLayout { /**Should the bubble be masked or not*/ - public var maskedBubble = true { + open var maskedBubble = true { didSet { self.updateBubbleConfig(self.bubbleConfiguration) self.setNeedsLayout() @@ -29,23 +29,23 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle // MARK: Private Variables /** ASCollectionNode as the content of the cell*/ - private var collectionViewMessageNode:ASCollectionNode = ASCollectionNode(collectionViewLayout: UICollectionViewFlowLayout()) + fileprivate var collectionViewMessageNode:ASCollectionNode = ASCollectionNode(collectionViewLayout: UICollectionViewFlowLayout()) /** [ASDisplayNode] as the posibble data of the cell*/ - private var collectionViewsDataSource: [ASDisplayNode]? + fileprivate var collectionViewsDataSource: [ASDisplayNode]? /** [UIView] as the posibble data of the cell*/ - private var viewsForDataSource: [UIView]? + fileprivate var viewsForDataSource: [UIView]? /** [ASDisplayNode] as the posibble data of the cell*/ - private var collectionNodesDataSource: [ASDisplayNode]? + fileprivate var collectionNodesDataSource: [ASDisplayNode]? /** CGSize as the max size of a cell in the collection view*/ - private var cellSize: CGSize = CGSizeMake(1, 1) + fileprivate var cellSize: CGSize = CGSize(width: 1, height: 1) /** CGFloat as the number of rows in the collection view*/ - private var collectionViewNumberOfRows: CGFloat = 1; + fileprivate var collectionViewNumberOfRows: CGFloat = 1; /** CGFloat as the number of rows in the collection view*/ - private var collectionViewNumberItemInRow: Int = 1; + fileprivate var collectionViewNumberItemInRow: Int = 1; /** CGFloat as the space between rows in the collection view*/ - private var spacingBetweenRows: CGFloat = 4 + fileprivate var spacingBetweenRows: CGFloat = 4 /** CGFloat as the space between cells in the collection view*/ - private var spacingBetweenCells: CGFloat = 4 + fileprivate var spacingBetweenCells: CGFloat = 4 // MARK: Initialisers /** @@ -72,7 +72,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle // MARK: Initialiser helper methods /** Override updateBubbleConfig to set bubble mask */ - public override func updateBubbleConfig(newValue: BubbleConfigurationProtocol) { + open override func updateBubbleConfig(_ newValue: BubbleConfigurationProtocol) { var maskedBubbleConfig = newValue maskedBubbleConfig.isMasked = self.maskedBubble super.updateBubbleConfig(maskedBubbleConfig) @@ -83,7 +83,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle - parameter customViews: Must be [UIView]. Sets views for the cell. - parameter rows: Must be CGFloat. Sets number of rows for the cell. */ - private func setupCustomViews(customViews: [UIView], numberOfRows rows:CGFloat) + fileprivate func setupCustomViews(_ customViews: [UIView], numberOfRows rows:CGFloat) { collectionViewNumberOfRows = rows @@ -107,13 +107,13 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() if rows==1 { - flowLayout.scrollDirection = .Horizontal + flowLayout.scrollDirection = .horizontal } flowLayout.itemSize = cellSize flowLayout.minimumInteritemSpacing = spacingBetweenCells flowLayout.minimumLineSpacing = spacingBetweenRows self.collectionViewMessageNode = ASCollectionNode(collectionViewLayout: flowLayout) - self.collectionViewMessageNode.backgroundColor = UIColor.whiteColor() + self.collectionViewMessageNode.backgroundColor = UIColor.white self.collectionViewMessageNode.accessibilityIdentifier = "CollectionViewWithCustomViews" @@ -125,7 +125,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle - parameter customViews: Must be [UIView]. Sets views for the cell. - parameter rows: Must be CGFloat. Sets number of rows for the cell. */ - private func setupCustomNodes(customNodes: [ASDisplayNode], numberOfRows rows:CGFloat) + fileprivate func setupCustomNodes(_ customNodes: [ASDisplayNode], numberOfRows rows:CGFloat) { collectionViewNumberOfRows = rows @@ -136,13 +136,13 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() if rows==1 { - flowLayout.scrollDirection = .Horizontal + flowLayout.scrollDirection = .horizontal } flowLayout.itemSize = cellSize flowLayout.minimumInteritemSpacing = spacingBetweenCells flowLayout.minimumLineSpacing = spacingBetweenRows self.collectionViewMessageNode = ASCollectionNode(collectionViewLayout: flowLayout) - self.collectionViewMessageNode.backgroundColor = UIColor.whiteColor() + self.collectionViewMessageNode.backgroundColor = UIColor.white self.collectionViewMessageNode.accessibilityIdentifier = "CollectionViewWithCustomNodes" self.addSubnode(collectionViewMessageNode) @@ -153,7 +153,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle /** Overriding didLoad to set asyncDataSource and asyncDelegate for collection view */ - override public func didLoad() { + override open func didLoad() { super.didLoad() @@ -166,15 +166,15 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { - let tmpConstrainedSize = ASSizeRange(min: constrainedSize.min, max: CGSizeMake(constrainedSize.max.width, constrainedSize.max.height)) + let tmpConstrainedSize = ASSizeRange(min: constrainedSize.min, max: CGSize(width: constrainedSize.max.width, height: constrainedSize.max.height)) if let tmp = self.collectionViewsDataSource { for node in tmp { - let nodeLayout = node.measureWithSizeRange(tmpConstrainedSize) + let nodeLayout = node.measure(with: tmpConstrainedSize) let nodeSize = nodeLayout.size if (isSmaller(cellSize,bigger: nodeSize)) { @@ -186,7 +186,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle { for node in tmp { - let nodeLayout = node.measureWithSizeRange(tmpConstrainedSize) + let nodeLayout = node.measure(with: tmpConstrainedSize) let nodeSize = nodeLayout.size node.preferredFrameSize = nodeSize if (isSmaller(cellSize,bigger: nodeSize)) @@ -218,7 +218,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle } } - self.collectionViewMessageNode.preferredFrameSize = CGSizeMake(width, height) + self.collectionViewMessageNode.preferredFrameSize = CGSize(width: width, height: height) let tmpSizeSpec = ASStaticLayoutSpec(children: [self.collectionViewMessageNode]) return tmpSizeSpec } @@ -230,7 +230,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle - parameter bigger: Must be CGSize Checks if one CGSize is smaller than another */ - private func isSmaller(smaller: CGSize, bigger: CGSize) -> Bool { + fileprivate func isSmaller(_ smaller: CGSize, bigger: CGSize) -> Bool { if(smaller.width >= bigger.width) { return false } @@ -245,14 +245,14 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle /** Implementing numberOfSectionsInCollectionView to define number of sections */ - public func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { + open func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 } /** Implementing numberOfItemsInSection to define number of items in section */ - public func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { if let viewDataSource = self.collectionViewsDataSource { return viewDataSource.count @@ -268,11 +268,11 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle /** Implementing nodeForItemAtIndexPath to define node at index path */ - public func collectionView(collectionView: ASCollectionView, nodeForItemAtIndexPath indexPath: NSIndexPath) -> ASCellNode { + open func collectionView(_ collectionView: ASCollectionView, nodeForItemAt indexPath: IndexPath) -> ASCellNode { var cellNode: ASCellNode = ASCellNode() if let nodeDataSource = self.collectionNodesDataSource { - let node = nodeDataSource[indexPath.row] + let node = nodeDataSource[(indexPath as NSIndexPath).row] let tmp = CustomContentCellNode(withCustomNode: node) cellNode = tmp @@ -284,7 +284,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle /** Implementing constrainedSizeForNodeAtIndexPath the size of each cell */ - public func collectionView(collectionView: ASCollectionView, constrainedSizeForNodeAtIndexPath indexPath: NSIndexPath) -> ASSizeRange { + open func collectionView(_ collectionView: ASCollectionView, constrainedSizeForNodeAt indexPath: IndexPath) -> ASSizeRange { return ASSizeRangeMake(cellSize, cellSize); } @@ -294,7 +294,7 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle /** Implementing insetForSectionAtIndex to define space between colums */ - public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets { + open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { if self.collectionViewNumberOfRows != 1 { return UIEdgeInsetsMake(0, 0, 0, 0) @@ -309,4 +309,4 @@ public class CollectionViewContentNode: ContentNode,ASCollectionDelegate,ASColle } } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/ContentNodes/CollectionViewContent/CustomContentCellNode.swift b/nMessenger/Source/MessageNodes/ContentNodes/CollectionViewContent/CustomContentCellNode.swift index d44a114..56b338a 100755 --- a/nMessenger/Source/MessageNodes/ContentNodes/CollectionViewContent/CustomContentCellNode.swift +++ b/nMessenger/Source/MessageNodes/ContentNodes/CollectionViewContent/CustomContentCellNode.swift @@ -16,11 +16,11 @@ import AsyncDisplayKit CustomContentCellNode class for N Messenger. Define the cell for CollectionViewContentNode */ -public class CustomContentCellNode: ASCellNode { +open class CustomContentCellNode: ASCellNode { // MARK: Public Variables /** ASDisplayNode as the content of the cell*/ - public var customContent:ASDisplayNode = ASDisplayNode() + open var customContent:ASDisplayNode = ASDisplayNode() // MARK: Initialisers @@ -40,7 +40,7 @@ public class CustomContentCellNode: ASCellNode { /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { let customContetntSpec = ASStaticLayoutSpec(children: [customContent]) return customContetntSpec } diff --git a/nMessenger/Source/MessageNodes/ContentNodes/ContentNode.swift b/nMessenger/Source/MessageNodes/ContentNodes/ContentNode.swift index cf9ff3b..9df2fd2 100755 --- a/nMessenger/Source/MessageNodes/ContentNodes/ContentNode.swift +++ b/nMessenger/Source/MessageNodes/ContentNodes/ContentNode.swift @@ -16,15 +16,15 @@ import AsyncDisplayKit Content node class for NMessenger. Define the content a a MessageNode or a MessageGroup */ -public class ContentNode: ASDisplayNode { +open class ContentNode: ASDisplayNode { // MARK: Public Parameters /** Bubble that defines the background for the message*/ - public var backgroundBubble: Bubble? + open var backgroundBubble: Bubble? /** UIViewController that holds the cell. Allows the cell the present View Controllers. Generally used for UIMenu or UIAlert Options*/ - public var currentViewController: UIViewController? + open var currentViewController: UIViewController? /** MessageConfigurationProtocol hold common definition for all messages. Defaults to **StandardMessageConfiguration***/ - public var bubbleConfiguration : BubbleConfigurationProtocol = StandardBubbleConfiguration() { + open var bubbleConfiguration : BubbleConfigurationProtocol = StandardBubbleConfiguration() { didSet { self.updateBubbleConfig(self.bubbleConfiguration) } @@ -32,7 +32,7 @@ public class ContentNode: ASDisplayNode { /** Bool if the cell is an incoming or out going message. Set backgroundBubble.bubbleColor when value is changed */ - public var isIncomingMessage = true { + open var isIncomingMessage = true { didSet { self.backgroundBubble?.bubbleColor = isIncomingMessage ? bubbleConfiguration.getIncomingColor() : bubbleConfiguration.getOutgoingColor() @@ -57,7 +57,7 @@ public class ContentNode: ASDisplayNode { /** Overriding didLoad and calling helper method addSublayers */ - override public func didLoad() { + override open func didLoad() { super.didLoad() self.addSublayers() } @@ -67,7 +67,7 @@ public class ContentNode: ASDisplayNode { /** Updates the bubble config by setting all necessary properties (background bubble, bubble color, layout) - parameter newValue: the new BubbleConfigurationProtocol */ - public func updateBubbleConfig(newValue: BubbleConfigurationProtocol) { + open func updateBubbleConfig(_ newValue: BubbleConfigurationProtocol) { self.backgroundBubble = self.bubbleConfiguration.getBubble() self.backgroundBubble?.bubbleColor = isIncomingMessage ? bubbleConfiguration.getIncomingColor() : bubbleConfiguration.getOutgoingColor() @@ -78,13 +78,13 @@ public class ContentNode: ASDisplayNode { /** Called during the initializer and makes sure layers are added on the main thread */ - public func addSublayers() { + open func addSublayers() { if let backgroundBubble = self.backgroundBubble { //make sure the layer is at the bottom of the node backgroundBubble.layer.removeFromSuperlayer() backgroundBubble.maskLayer.removeFromSuperlayer() - self.layer.insertSublayer(backgroundBubble.layer, atIndex: 0) + self.layer.insertSublayer(backgroundBubble.layer, at: 0) //If there is a layer mask, add it if backgroundBubble.hasLayerMask { @@ -100,14 +100,14 @@ public class ContentNode: ASDisplayNode { /** Draws the content in the bubble. This is called on a background thread. */ - public func drawRect(bounds: CGRect, withParameters parameters: NSObjectProtocol!, + open func drawRect(_ bounds: CGRect, withParameters parameters: NSObjectProtocol!, isCancelled isCancelledBlock: asdisplaynode_iscancelled_block_t, isRasterizing: Bool) { - self.opaque = false + self.isOpaque = false if !isRasterizing { self.calculateLayerPropertiesThatFit(bounds) //call the main queue - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { self.layoutLayers() } } @@ -120,7 +120,7 @@ public class ContentNode: ASDisplayNode { Called through the draw rect function. This should be used to create a background layer off the main thread. This layer should be added in layout. - parameter bounds: Must be CGRect */ - public func calculateLayerPropertiesThatFit(bounds: CGRect) { + open func calculateLayerPropertiesThatFit(_ bounds: CGRect) { if let backgroundBubble = self.backgroundBubble { backgroundBubble.sizeToBounds(bounds) } @@ -129,7 +129,7 @@ public class ContentNode: ASDisplayNode { /** Called on the main thread */ - public func layoutLayers() { + open func layoutLayers() { if let backgroundBubble = self.backgroundBubble { backgroundBubble.createLayer() @@ -149,14 +149,10 @@ public class ContentNode: ASDisplayNode { - parameter delay: Must be Double. - parameter closure: Must be an ()->() */ - public func delay(delay: Double, closure: ()->()) { - dispatch_after( - dispatch_time( - DISPATCH_TIME_NOW, - Int64(delay * Double(NSEC_PER_SEC)) - ), - dispatch_get_main_queue(), - closure + open func delay(_ delay: Double, closure: @escaping ()->()) { + DispatchQueue.main.asyncAfter( + deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), + execute: closure ) } @@ -167,7 +163,7 @@ public class ContentNode: ASDisplayNode { Selector to handle long press on message and show custom menu - parameter recognizer: Must be UITapGestureRecognizer */ - public func messageNodeLongPressSelector(recognizer: UITapGestureRecognizer) { + open func messageNodeLongPressSelector(_ recognizer: UITapGestureRecognizer) { } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/ContentNodes/CustomContentContent/CustomContentNode.swift b/nMessenger/Source/MessageNodes/ContentNodes/CustomContentContent/CustomContentNode.swift index 742598c..f387345 100755 --- a/nMessenger/Source/MessageNodes/ContentNodes/CustomContentContent/CustomContentNode.swift +++ b/nMessenger/Source/MessageNodes/ContentNodes/CustomContentContent/CustomContentNode.swift @@ -16,17 +16,17 @@ import AsyncDisplayKit Custom View Message class for NMessenger. Extends ContentNode. Defines content that is a custom. Content can be a view or a node. */ -public class CustomContentNode: ContentNode { +open class CustomContentNode: ContentNode { // MARK: Public Variables /** Insets for the node */ - public var insets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) { + open var insets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) { didSet { setNeedsLayout() } } /**Should the bubble be masked or not*/ - public var maskedBubble = true { + open var maskedBubble = true { didSet { self.updateBubbleConfig(self.bubbleConfiguration) self.setNeedsLayout() @@ -35,11 +35,11 @@ public class CustomContentNode: ContentNode { // MARK: Private Variables /** ASCollectionNode as the content of the cell*/ - public private(set) var customContentMessageNode:ASDisplayNode = ASDisplayNode() + open fileprivate(set) var customContentMessageNode:ASDisplayNode = ASDisplayNode() /** UIView as the posiible view of the cell*/ - private var customView:UIView? + fileprivate var customView:UIView? /** ASDisplayNode as the posiible view of the cell*/ - private var customNode:ASDisplayNode? + fileprivate var customNode:ASDisplayNode? // MARK: Initialisers @@ -66,7 +66,7 @@ public class CustomContentNode: ContentNode { // MARK: Initialiser helper methods /** Override updateBubbleConfig to set bubble mask */ - public override func updateBubbleConfig(newValue: BubbleConfigurationProtocol) { + open override func updateBubbleConfig(_ newValue: BubbleConfigurationProtocol) { var maskedBubbleConfig = newValue maskedBubbleConfig.isMasked = self.maskedBubble super.updateBubbleConfig(maskedBubbleConfig) @@ -76,10 +76,10 @@ public class CustomContentNode: ContentNode { Adds subview to the content - parameter customView: Must be UIView. Sets view for the cell. */ - private func setupCustomView(customView: UIView) + fileprivate func setupCustomView(_ customView: UIView) { self.customView = customView - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { self.customContentMessageNode.view.addSubview(customView) self.customContentMessageNode.preferredFrameSize = customView.frame.size } @@ -90,11 +90,11 @@ public class CustomContentNode: ContentNode { Adds subnode to the content - parameter customNode: Must be ASDisplayNode. Sets view for the cell. */ - private func setupCustomNode(customNode: ASDisplayNode) + fileprivate func setupCustomNode(_ customNode: ASDisplayNode) { - self.userInteractionEnabled = true + self.isUserInteractionEnabled = true self.customNode = customNode - self.customNode?.userInteractionEnabled = true + self.customNode?.isUserInteractionEnabled = true customContentMessageNode = customNode self.addSubnode(customContentMessageNode) } @@ -104,14 +104,14 @@ public class CustomContentNode: ContentNode { /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { let width = constrainedSize.max.width - let tmp = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(width),ASRelativeDimensionMakeWithPercent(1))) + let tmp = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSize.zero), ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(width),ASRelativeDimensionMakeWithPercent(1))) customContentMessageNode.sizeRange = tmp let customContetntSpec = ASStaticLayoutSpec(children: [customContentMessageNode]) return ASInsetLayoutSpec(insets: insets, child: customContetntSpec) } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/ContentNodes/ImageContent/ImageContentNode.swift b/nMessenger/Source/MessageNodes/ContentNodes/ImageContent/ImageContentNode.swift index 658777d..9b48174 100755 --- a/nMessenger/Source/MessageNodes/ContentNodes/ImageContent/ImageContentNode.swift +++ b/nMessenger/Source/MessageNodes/ContentNodes/ImageContent/ImageContentNode.swift @@ -16,11 +16,11 @@ import AsyncDisplayKit ImageContentNode for NMessenger. Extends ContentNode. Defines content that is an image. */ -public class ImageContentNode: ContentNode { +open class ImageContentNode: ContentNode { // MARK: Public Variables /** UIImage as the image of the cell*/ - public var image: UIImage? { + open var image: UIImage? { get { return imageMessageNode.image } set { @@ -30,7 +30,7 @@ public class ImageContentNode: ContentNode { // MARK: Private Variables /** ASImageNode as the content of the cell*/ - public private(set) var imageMessageNode:ASImageNode = ASImageNode() + open fileprivate(set) var imageMessageNode:ASImageNode = ASImageNode() // MARK: Initialisers @@ -47,7 +47,7 @@ public class ImageContentNode: ContentNode { // MARK: Initialiser helper method /** Override updateBubbleConfig to set bubble mask */ - public override func updateBubbleConfig(newValue: BubbleConfigurationProtocol) { + open override func updateBubbleConfig(_ newValue: BubbleConfigurationProtocol) { var maskedBubbleConfig = newValue maskedBubbleConfig.isMasked = true super.updateBubbleConfig(maskedBubbleConfig) @@ -57,11 +57,11 @@ public class ImageContentNode: ContentNode { Sets the image to be display in the cell. Clips and rounds the corners. - parameter image: Must be UIImage. Sets image for cell. */ - private func setupImageNode(image: UIImage) + fileprivate func setupImageNode(_ image: UIImage) { imageMessageNode.image = image imageMessageNode.clipsToBounds = true - imageMessageNode.contentMode = UIViewContentMode.ScaleAspectFill + imageMessageNode.contentMode = UIViewContentMode.scaleAspectFill self.imageMessageNode.accessibilityIdentifier = "imageNode" self.imageMessageNode.isAccessibilityElement = true self.addSubnode(imageMessageNode) @@ -73,11 +73,11 @@ public class ImageContentNode: ContentNode { /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { - let width = UIScreen.mainScreen().bounds.width/3*2 + let width = UIScreen.main.bounds.width/3*2 - imageMessageNode.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(CGSizeMake(width, width/4*3)) + imageMessageNode.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(CGSize(width: width, height: width/4*3)) return ASStaticLayoutSpec(children: [self.imageMessageNode]) } @@ -86,25 +86,25 @@ public class ImageContentNode: ContentNode { /** Overriding canBecomeFirstResponder to make cell first responder */ - override public func canBecomeFirstResponder() -> Bool { + override open func canBecomeFirstResponder() -> Bool { return true } /** Override method from superclass */ - public override func messageNodeLongPressSelector(recognizer: UITapGestureRecognizer) { - if recognizer.state == UIGestureRecognizerState.Began { + open override func messageNodeLongPressSelector(_ recognizer: UITapGestureRecognizer) { + if recognizer.state == UIGestureRecognizerState.began { - let touchLocation = recognizer.locationInView(view) - if CGRectContainsPoint(self.imageMessageNode.frame, touchLocation) { + let touchLocation = recognizer.location(in: view) + if self.imageMessageNode.frame.contains(touchLocation) { view.becomeFirstResponder() delay(0.1, closure: { - let menuController = UIMenuController.sharedMenuController() + let menuController = UIMenuController.shared menuController.menuItems = [UIMenuItem(title: "Copy", action: #selector(ImageContentNode.copySelector))] - menuController.setTargetRect(self.imageMessageNode.frame, inView: self.view) + menuController.setTargetRect(self.imageMessageNode.frame, in: self.view) menuController.setMenuVisible(true, animated:true) }) } @@ -115,9 +115,9 @@ public class ImageContentNode: ContentNode { Copy Selector for UIMenuController Puts the node's image on UIPasteboard */ - public func copySelector() { + open func copySelector() { if let image = self.image { - UIPasteboard.generalPasteboard().image = image + UIPasteboard.general.image = image } } diff --git a/nMessenger/Source/MessageNodes/ContentNodes/NetworkImageContent/NetworkImageContentNode.swift b/nMessenger/Source/MessageNodes/ContentNodes/NetworkImageContent/NetworkImageContentNode.swift index 170eccd..803e7d3 100755 --- a/nMessenger/Source/MessageNodes/ContentNodes/NetworkImageContent/NetworkImageContentNode.swift +++ b/nMessenger/Source/MessageNodes/ContentNodes/NetworkImageContent/NetworkImageContentNode.swift @@ -16,21 +16,21 @@ import AsyncDisplayKit NetworkImageContentNode class for N Messenger. Extends MessageNode. Defines content that is a network image (An image that is provided via url). */ -public class NetworkImageContentNode: ContentNode,ASNetworkImageNodeDelegate { +open class NetworkImageContentNode: ContentNode,ASNetworkImageNodeDelegate { // MARK: Public Variables /** NSURL for the image*/ - public var url: NSURL? { + open var url: URL? { get { - return networkImageMessageNode.URL + return networkImageMessageNode.url } set { - networkImageMessageNode.URL = newValue + networkImageMessageNode.url = newValue } } // MARK: Private Variables /** ASNetworkImageNode as the content of the cell*/ - public private(set) var networkImageMessageNode:ASNetworkImageNode = ASNetworkImageNode() + open fileprivate(set) var networkImageMessageNode:ASNetworkImageNode = ASNetworkImageNode() // MARK: Initialisers @@ -46,7 +46,7 @@ public class NetworkImageContentNode: ContentNode,ASNetworkImageNodeDelegate { // MARK: Initialiser helper method /** Override updateBubbleConfig to set bubble mask */ - public override func updateBubbleConfig(newValue: BubbleConfigurationProtocol) { + open override func updateBubbleConfig(_ newValue: BubbleConfigurationProtocol) { var maskedBubbleConfig = newValue maskedBubbleConfig.isMasked = true super.updateBubbleConfig(maskedBubbleConfig) @@ -56,9 +56,9 @@ public class NetworkImageContentNode: ContentNode,ASNetworkImageNodeDelegate { Sets the URL to be display in the image. Clips and rounds the corners. - parameter imageURL: Must be String. Sets url for the image in the cell. */ - private func setupNetworkImageNode(imageURL: String) + fileprivate func setupNetworkImageNode(_ imageURL: String) { - networkImageMessageNode.URL = NSURL(string: imageURL) + networkImageMessageNode.url = URL(string: imageURL) networkImageMessageNode.shouldCacheImage = true networkImageMessageNode.delegate = self self.addSubnode(networkImageMessageNode) @@ -70,10 +70,10 @@ public class NetworkImageContentNode: ContentNode,ASNetworkImageNodeDelegate { /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { - let width = UIScreen.mainScreen().bounds.width/3*2 - self.networkImageMessageNode.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(CGSizeMake(width, width/4*3)) + let width = UIScreen.main.bounds.width/3*2 + self.networkImageMessageNode.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(CGSize(width: width, height: width/4*3)) return ASStaticLayoutSpec(children: [self.networkImageMessageNode]) } @@ -81,7 +81,7 @@ public class NetworkImageContentNode: ContentNode,ASNetworkImageNodeDelegate { /** Overriding didLoadImage to layout the node once the image is loaded */ - public func imageNode(imageNode: ASNetworkImageNode, didLoadImage image: UIImage) { + open func imageNode(_ imageNode: ASNetworkImageNode, didLoad image: UIImage) { self.setNeedsLayout() } @@ -90,25 +90,25 @@ public class NetworkImageContentNode: ContentNode,ASNetworkImageNodeDelegate { /** Overriding canBecomeFirstResponder to make cell first responder */ - override public func canBecomeFirstResponder() -> Bool { + override open func canBecomeFirstResponder() -> Bool { return true } /** Override method from superclass */ - public override func messageNodeLongPressSelector(recognizer: UITapGestureRecognizer) { - if recognizer.state == UIGestureRecognizerState.Began { + open override func messageNodeLongPressSelector(_ recognizer: UITapGestureRecognizer) { + if recognizer.state == UIGestureRecognizerState.began { - let touchLocation = recognizer.locationInView(view) - if CGRectContainsPoint(self.networkImageMessageNode.frame, touchLocation) { + let touchLocation = recognizer.location(in: view) + if self.networkImageMessageNode.frame.contains(touchLocation) { view.becomeFirstResponder() delay(0.1, closure: { - let menuController = UIMenuController.sharedMenuController() + let menuController = UIMenuController.shared menuController.menuItems = [UIMenuItem(title: "Copy", action: #selector(NetworkImageContentNode.copySelector))] - menuController.setTargetRect(self.networkImageMessageNode.frame, inView: self.view) + menuController.setTargetRect(self.networkImageMessageNode.frame, in: self.view) menuController.setMenuVisible(true, animated:true) }) } @@ -119,9 +119,9 @@ public class NetworkImageContentNode: ContentNode,ASNetworkImageNodeDelegate { Copy Selector for UIMenuController Puts the node's image on UIPasteboard */ - public func copySelector() { + open func copySelector() { if let image = self.networkImageMessageNode.image { - UIPasteboard.generalPasteboard().image = image + UIPasteboard.general.image = image } } diff --git a/nMessenger/Source/MessageNodes/ContentNodes/TextContent/TextContentNode.swift b/nMessenger/Source/MessageNodes/ContentNodes/TextContent/TextContentNode.swift index 672ae7d..13ccc65 100755 --- a/nMessenger/Source/MessageNodes/ContentNodes/TextContent/TextContentNode.swift +++ b/nMessenger/Source/MessageNodes/ContentNodes/TextContent/TextContentNode.swift @@ -16,41 +16,41 @@ import AsyncDisplayKit TextMessageNode class for N Messenger. Extends MessageNode. Defines content that is a text. */ -public class TextContentNode: ContentNode,ASTextNodeDelegate { +open class TextContentNode: ContentNode,ASTextNodeDelegate { // MARK: Public Variables /** Insets for the node */ - public var insets = UIEdgeInsets(top: 8, left: 10, bottom: 8, right: 10) { + open var insets = UIEdgeInsets(top: 8, left: 10, bottom: 8, right: 10) { didSet { setNeedsLayout() } } /** UIFont for incoming text messages*/ - public var incomingTextFont = UIFont.n1B1Font() { + open var incomingTextFont = UIFont.n1B1Font() { didSet { self.updateAttributedText() } } /** UIFont for outgoinf text messages*/ - public var outgoingTextFont = UIFont.n1B1Font() { + open var outgoingTextFont = UIFont.n1B1Font() { didSet { self.updateAttributedText() } } /** UIColor for incoming text messages*/ - public var incomingTextColor = UIColor.n1DarkestGreyColor() { + open var incomingTextColor = UIColor.n1DarkestGreyColor() { didSet { self.updateAttributedText() } } /** UIColor for outgoinf text messages*/ - public var outgoingTextColor = UIColor.n1WhiteColor() { + open var outgoingTextColor = UIColor.n1WhiteColor() { didSet { self.updateAttributedText() } } /** String to present as the content of the cell*/ - public var textMessageString: NSAttributedString? { + open var textMessageString: NSAttributedString? { get { return self.textMessageNode.attributedString } set { @@ -60,7 +60,7 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { /** Overriding from super class Set backgroundBubble.bubbleColor and the text color when valus is set */ - public override var isIncomingMessage: Bool + open override var isIncomingMessage: Bool { didSet { if isIncomingMessage @@ -76,9 +76,9 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { // MARK: Private Variables /** ASTextNode as the content of the cell*/ - public private(set) var textMessageNode:ASTextNode = ASTextNode() + open fileprivate(set) var textMessageNode:ASTextNode = ASTextNode() /** Bool as mutex for handling attributed link long presses*/ - private var lockKey: Bool = false + fileprivate var lockKey: Bool = false // MARK: Initialisers @@ -112,29 +112,29 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { Creates the text to be display in the cell. Finds links and phone number in the string and creates atrributed string. - parameter textMessageString: Must be String. Sets text for cell. */ - private func setupTextNode(textMessageString: String) + fileprivate func setupTextNode(_ textMessageString: String) { self.backgroundBubble = self.bubbleConfiguration.getBubble() textMessageNode.delegate = self - textMessageNode.userInteractionEnabled = true + textMessageNode.isUserInteractionEnabled = true textMessageNode.linkAttributeNames = ["LinkAttribute","PhoneNumberAttribute"] let fontAndSizeAndTextColor = [ NSFontAttributeName: self.isIncomingMessage ? incomingTextFont : outgoingTextFont, NSForegroundColorAttributeName: self.isIncomingMessage ? incomingTextColor : outgoingTextColor] let outputString = NSMutableAttributedString(string: textMessageString, attributes: fontAndSizeAndTextColor ) - let types: NSTextCheckingType = [.Link, .PhoneNumber] + let types: NSTextCheckingResult.CheckingType = [.link, .phoneNumber] let detector = try! NSDataDetector(types: types.rawValue) - let matches = detector.matchesInString(textMessageString, options: [], range: NSMakeRange(0, textMessageString.characters.count)) + let matches = detector.matches(in: textMessageString, options: [], range: NSMakeRange(0, textMessageString.characters.count)) for match in matches { - if let url = match.URL + if let url = match.url { outputString.addAttribute("LinkAttribute", value: url, range: match.range) - outputString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: match.range) - outputString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor(), range: match.range) + outputString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: match.range) + outputString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blue, range: match.range) } if let phoneNumber = match.phoneNumber { outputString.addAttribute("PhoneNumberAttribute", value: phoneNumber, range: match.range) - outputString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: match.range) - outputString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor(), range: match.range) + outputString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: match.range) + outputString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blue, range: match.range) } } self.textMessageNode.attributedString = outputString @@ -145,7 +145,7 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { //MARK: Helper Methods /** Updates the attributed string to the correct incoming/outgoing settings and lays out the component again*/ - private func updateAttributedText() { + fileprivate func updateAttributedText() { let tmpString = NSMutableAttributedString(attributedString: self.textMessageNode.attributedString!) tmpString.addAttributes([NSForegroundColorAttributeName: isIncomingMessage ? incomingTextColor : outgoingTextColor, NSFontAttributeName: isIncomingMessage ? incomingTextFont : outgoingTextFont], range: NSMakeRange(0, tmpString.length)) self.textMessageNode.attributedString = tmpString @@ -158,10 +158,10 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { let width = constrainedSize.max.width * 0.90 - self.insets.left - self.insets.right - let tmp = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(width),ASRelativeDimensionMakeWithPercent(1))) + let tmp = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSize.zero), ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(width),ASRelativeDimensionMakeWithPercent(1))) textMessageNode.sizeRange = tmp @@ -176,7 +176,8 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { /** Implementing shouldHighlightLinkAttribute - returning true for both link and phone numbers */ - public func textNode(textNode: ASTextNode, shouldHighlightLinkAttribute attribute: String, value: AnyObject, atPoint point: CGPoint) -> Bool { + + public func textNode(_ textNode: ASTextNode, shouldHighlightLinkAttribute attribute: String, value: Any, at point: CGPoint) -> Bool { if attribute == "LinkAttribute" { return true @@ -186,12 +187,27 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { return true } return false + } + /*open func textNode(_ textNode: ASTextNode, shouldHighlightLinkAttribute attribute: String, value: AnyObject, at point: CGPoint) -> Bool { + if attribute == "LinkAttribute" + { + return true + } + else if attribute == "PhoneNumberAttribute" + { + return true + } + return false + }*/ + /** Implementing tappedLinkAttribute - handle tap event on links and phone numbers */ - public func textNode(textNode: ASTextNode, tappedLinkAttribute attribute: String, value: AnyObject, atPoint point: CGPoint, textRange: NSRange) { + + //open func textNode(_ textNode: ASTextNode, tappedLinkAttribute attribute: String, value: AnyObject, at point: CGPoint, textRange: NSRange) { + public func textNode(_ textNode: ASTextNode, tappedLinkAttribute attribute: String, value: Any, at point: CGPoint, textRange: NSRange) { if attribute == "LinkAttribute" { if !self.lockKey @@ -199,9 +215,9 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { if let tmpString = self.textMessageNode.attributedString { let attributedString = NSMutableAttributedString(attributedString: tmpString) - attributedString.addAttribute(NSBackgroundColorAttributeName, value: UIColor.lightGrayColor(), range: textRange) + attributedString.addAttribute(NSBackgroundColorAttributeName, value: UIColor.lightGray, range: textRange) self.textMessageNode.attributedString = attributedString - UIApplication.sharedApplication().openURL(value as! NSURL) + UIApplication.shared.openURL(value as! URL) delay(0.4) { if let tmpString = self.textMessageNode.attributedString { @@ -216,14 +232,15 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { else if attribute == "PhoneNumberAttribute" { let phoneNumber = value as! String - UIApplication.sharedApplication().openURL(NSURL(string: "tel://\(phoneNumber)")!) + UIApplication.shared.openURL(URL(string: "tel://\(phoneNumber)")!) } } /** Implementing shouldLongPressLinkAttribute - returning true for both link and phone numbers */ - public func textNode(textNode: ASTextNode, shouldLongPressLinkAttribute attribute: String, value: AnyObject, atPoint point: CGPoint) -> Bool { + //open func textNode(_ textNode: ASTextNode, shouldLongPressLinkAttribute attribute: String, value: AnyObject, at point: CGPoint) -> Bool { + public func textNode(_ textNode: ASTextNode, shouldLongPressLinkAttribute attribute: String, value: Any, at point: CGPoint) -> Bool { if attribute == "LinkAttribute" { return true @@ -238,33 +255,34 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { /** Implementing longPressedLinkAttribute - handles long tap event on links and phone numbers */ - public func textNode(textNode: ASTextNode, longPressedLinkAttribute attribute: String, value: AnyObject, atPoint point: CGPoint, textRange: NSRange) { + //open func textNode(_ textNode: ASTextNode, longPressedLinkAttribute attribute: String, value: AnyObject, at point: CGPoint, textRange: NSRange) { + public func textNode(_ textNode: ASTextNode, longPressedLinkAttribute attribute: String, value: Any, at point: CGPoint, textRange: NSRange) { if attribute == "LinkAttribute" { self.lockKey = true if let tmpString = self.textMessageNode.attributedString { let attributedString = NSMutableAttributedString(attributedString: tmpString) - attributedString.addAttribute(NSBackgroundColorAttributeName, value: UIColor.lightGrayColor(), range: textRange) + attributedString.addAttribute(NSBackgroundColorAttributeName, value: UIColor.lightGray, range: textRange) self.textMessageNode.attributedString = attributedString - let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) + let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - let openAction = UIAlertAction(title: "Open", style: .Default, handler: { + let openAction = UIAlertAction(title: "Open", style: .default, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) - let addToReadingListAction = UIAlertAction(title: "Add to Reading List", style: .Default, handler: { + let addToReadingListAction = UIAlertAction(title: "Add to Reading List", style: .default, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) - let copyAction = UIAlertAction(title: "Copy", style: .Default, handler: { + let copyAction = UIAlertAction(title: "Copy", style: .default, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) - let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: { + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) @@ -276,8 +294,8 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { if let tmpCurrentViewController = self.currentViewController { - dispatch_async(dispatch_get_main_queue(), { () -> Void in - tmpCurrentViewController.presentViewController(optionMenu, animated: true, completion: nil) + DispatchQueue.main.async(execute: { () -> Void in + tmpCurrentViewController.present(optionMenu, animated: true, completion: nil) }) } @@ -299,35 +317,35 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { if let tmpString = self.textMessageNode.attributedString { let attributedString = NSMutableAttributedString(attributedString: tmpString) - attributedString.addAttribute(NSBackgroundColorAttributeName, value: UIColor.lightGrayColor(), range: textRange) + attributedString.addAttribute(NSBackgroundColorAttributeName, value: UIColor.lightGray, range: textRange) self.textMessageNode.attributedString = attributedString - let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) + let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - let callPhoneNumberAction = UIAlertAction(title: "Call \(phoneNumber)", style: .Default, handler: { + let callPhoneNumberAction = UIAlertAction(title: "Call \(phoneNumber)", style: .default, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) - let facetimeAudioAction = UIAlertAction(title: "Facetime Audio", style: .Default, handler: { + let facetimeAudioAction = UIAlertAction(title: "Facetime Audio", style: .default, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) - let sendMessageAction = UIAlertAction(title: "Send Message", style: .Default, handler: { + let sendMessageAction = UIAlertAction(title: "Send Message", style: .default, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) - let addToContactsAction = UIAlertAction(title: "Add to Contacts", style: .Default, handler: { + let addToContactsAction = UIAlertAction(title: "Add to Contacts", style: .default, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) - let copyAction = UIAlertAction(title: "Copy", style: .Default, handler: { + let copyAction = UIAlertAction(title: "Copy", style: .default, handler: { (alert: UIAlertAction) -> Void in self.lockKey = false }) - let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: { + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { (alert: UIAlertAction) -> Void in //print("Cancelled") self.lockKey = false @@ -342,8 +360,8 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { if let tmpCurrentViewController = self.currentViewController { - dispatch_async(dispatch_get_main_queue(), { () -> Void in - tmpCurrentViewController.presentViewController(optionMenu, animated: true, completion: nil) + DispatchQueue.main.async(execute: { () -> Void in + tmpCurrentViewController.present(optionMenu, animated: true, completion: nil) }) } @@ -366,28 +384,28 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { /** Overriding canBecomeFirstResponder to make cell first responder */ - override public func canBecomeFirstResponder() -> Bool { + override open func canBecomeFirstResponder() -> Bool { return true } /** Overriding resignFirstResponder to resign responder */ - override public func resignFirstResponder() -> Bool { + override open func resignFirstResponder() -> Bool { return view.resignFirstResponder() } /** Override method from superclass */ - public override func messageNodeLongPressSelector(recognizer: UITapGestureRecognizer) { - if recognizer.state == UIGestureRecognizerState.Began { - let touchLocation = recognizer.locationInView(view) - if CGRectContainsPoint(self.textMessageNode.frame, touchLocation) { + open override func messageNodeLongPressSelector(_ recognizer: UITapGestureRecognizer) { + if recognizer.state == UIGestureRecognizerState.began { + let touchLocation = recognizer.location(in: view) + if self.textMessageNode.frame.contains(touchLocation) { becomeFirstResponder() delay(0.1, closure: { - let menuController = UIMenuController.sharedMenuController() + let menuController = UIMenuController.shared menuController.menuItems = [UIMenuItem(title: "Copy", action: #selector(TextContentNode.copySelector))] - menuController.setTargetRect(self.textMessageNode.frame, inView: self.view) + menuController.setTargetRect(self.textMessageNode.frame, in: self.view) menuController.setMenuVisible(true, animated:true) }) } @@ -397,8 +415,8 @@ public class TextContentNode: ContentNode,ASTextNodeDelegate { /** Copy Selector for UIMenuController */ - public func copySelector() { - UIPasteboard.generalPasteboard().string = self.textMessageNode.attributedString!.string + open func copySelector() { + UIPasteboard.general.string = self.textMessageNode.attributedString!.string } } diff --git a/nMessenger/Source/MessageNodes/ContentNodes/TypingIndicatorContent/TypingIndicatorContent.swift b/nMessenger/Source/MessageNodes/ContentNodes/TypingIndicatorContent/TypingIndicatorContent.swift index c1bd625..d6ebbd7 100755 --- a/nMessenger/Source/MessageNodes/ContentNodes/TypingIndicatorContent/TypingIndicatorContent.swift +++ b/nMessenger/Source/MessageNodes/ContentNodes/TypingIndicatorContent/TypingIndicatorContent.swift @@ -17,27 +17,27 @@ import AsyncDisplayKit TypingIndicatorContent class for NMessenger. Extends MessageNode. Defines content that is a loading indicator. */ -public class TypingIndicatorContent: ContentNode { +open class TypingIndicatorContent: ContentNode { // MARK: Private Variables /** gifNode holds the animated typing indicator*/ - public private(set) var gifNode = ASDisplayNode() + open fileprivate(set) var gifNode = ASDisplayNode() - override public func didLoad() { + override open func didLoad() { super.didLoad() let imageNames = ["loadBubble_0038_Layer-1", "loadBubble_0037_Layer-2", "loadBubble_0036_Layer-3", "loadBubble_0035_Layer-4", "loadBubble_0034_Layer-5", "loadBubble_0033_Layer-6", "loadBubble_0032_Layer-7", "loadBubble_0031_Layer-8", "loadBubble_0030_Layer-9", "loadBubble_0029_Layer-10", "loadBubble_0028_Layer-11", "loadBubble_0027_Layer-12", "loadBubble_0026_Layer-13", "loadBubble_0025_Layer-14", "loadBubble_0024_Layer-15", "loadBubble_0023_Layer-16", "loadBubble_0022_Layer-17", "loadBubble_0021_Layer-18", "loadBubble_0020_Layer-19", "loadBubble_0019_Layer-20", "loadBubble_0018_Layer-21", "loadBubble_0017_Layer-22", "loadBubble_0016_Layer-23", "loadBubble_0015_Layer-24", "loadBubble_0014_Layer-25", "loadBubble_0013_Layer-26", "loadBubble_0012_Layer-27", "loadBubble_0011_Layer-28", "loadBubble_0010_Layer-29", "loadBubble_0009_Layer-30", "loadBubble_0008_Layer-31", "loadBubble_0007_Layer-32", "loadBubble_0006_Layer-33", "loadBubble_0005_Layer-34", "loadBubble_0004_Layer-35", "loadBubble_0003_Layer-36", "loadBubble_0002_Layer-37", "loadBubble_0001_Layer-38", "loadBubble_0000_Layer-39"] var images = [UIImage]() for imageName in imageNames { - if let image = UIImage(named: imageName, inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil){ + if let image = UIImage(named: imageName, in: Bundle(for: NMessengerViewController.self), compatibleWith: nil){ images.append(image) } } let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: images[0].size.width - 1, height: images[0].size.height - 1)) - imageView.backgroundColor = UIColor.orangeColor() - imageView.contentMode = UIViewContentMode.Center + imageView.backgroundColor = UIColor.orange + imageView.contentMode = UIViewContentMode.center imageView.clipsToBounds = true imageView.animationImages = images imageView.animationDuration = 1 @@ -56,7 +56,7 @@ public class TypingIndicatorContent: ContentNode { /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { return ASStaticLayoutSpec(children: [self.gifNode]) } diff --git a/nMessenger/Source/MessageNodes/GeneralMessageCell/GeneralMessengerCell.swift b/nMessenger/Source/MessageNodes/GeneralMessageCell/GeneralMessengerCell.swift index 588cd3a..73a77df 100755 --- a/nMessenger/Source/MessageNodes/GeneralMessageCell/GeneralMessengerCell.swift +++ b/nMessenger/Source/MessageNodes/GeneralMessageCell/GeneralMessengerCell.swift @@ -16,17 +16,17 @@ import AsyncDisplayKit GeneralMessengerCell class for NMessenger. Extends ASCellNode. Defines the base class for all messages in NMessenger. */ -public class GeneralMessengerCell: ASCellNode { +open class GeneralMessengerCell: ASCellNode { // MARK: Public Variables /** UIEdgeInsets for cell*/ - public var cellPadding: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0) + open var cellPadding: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0) /** UIViewController that holds the cell. Allows the cell the present View Controllers*/ - public var currentViewController: UIViewController? + open var currentViewController: UIViewController? /** The current table in which this node resides*/ - public var currentTableNode: ASTableNode? + open var currentTableNode: ASTableNode? /** message incoming/outgoing */ - public var isIncomingMessage:Bool = true + open var isIncomingMessage:Bool = true // MARK: Initialisers /** @@ -35,7 +35,7 @@ public class GeneralMessengerCell: ASCellNode { */ public override init() { super.init() - selectionStyle = .None + selectionStyle = .none cellPadding = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0) } /** diff --git a/nMessenger/Source/MessageNodes/Indicators/HeadLoadingIndicator.swift b/nMessenger/Source/MessageNodes/Indicators/HeadLoadingIndicator.swift index 85d0e83..2fdc319 100755 --- a/nMessenger/Source/MessageNodes/Indicators/HeadLoadingIndicator.swift +++ b/nMessenger/Source/MessageNodes/Indicators/HeadLoadingIndicator.swift @@ -15,19 +15,19 @@ import UIKit /** Spinning loading indicator class. Used by the NMessenger prefetch. */ -public class HeadLoadingIndicator: GeneralMessengerCell { +open class HeadLoadingIndicator: GeneralMessengerCell { /** Horizontal spacing between text and spinner. Defaults to 20.*/ - public var contentPadding:CGFloat = 20 { + open var contentPadding:CGFloat = 20 { didSet { self.setNeedsLayout() } } /** Animated spinner node*/ - public let spinner = SpinnerNode() + open let spinner = SpinnerNode() /** Loading text node*/ - public let text = ASTextNode() + open let text = ASTextNode() /** Sets the loading attributed text for the spinner. Defaults to *"Loading..."* */ - public var loadingAttributedText:NSAttributedString? { + open var loadingAttributedText:NSAttributedString? { set { text.attributedString = newValue self.setNeedsLayout() @@ -42,19 +42,19 @@ public class HeadLoadingIndicator: GeneralMessengerCell { text.attributedString = NSAttributedString( string: "Loading…", attributes: [ - NSFontAttributeName: UIFont.systemFontOfSize(12), - NSForegroundColorAttributeName: UIColor.lightGrayColor(), + NSFontAttributeName: UIFont.systemFont(ofSize: 12), + NSForegroundColorAttributeName: UIColor.lightGray, NSKernAttributeName: -0.3 ]) addSubnode(spinner) } - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { let stackLayout = ASStackLayoutSpec( - direction: .Horizontal, + direction: .horizontal, spacing: contentPadding, - justifyContent: .Center, - alignItems: .Center, + justifyContent: .center, + alignItems: .center, children: [ text, spinner ]) let paddingLayout = ASInsetLayoutSpec(insets: cellPadding, child: stackLayout) return paddingLayout @@ -65,18 +65,18 @@ public class HeadLoadingIndicator: GeneralMessengerCell { /** Animated spinner. Used by HeadLoadingIndicator. Defaults to *preferredFrameSize.height=32* */ -public class SpinnerNode: ASDisplayNode { - public var activityIndicatorView: UIActivityIndicatorView { +open class SpinnerNode: ASDisplayNode { + open var activityIndicatorView: UIActivityIndicatorView { return view as! UIActivityIndicatorView } public override init() { - super.init(viewBlock: { UIActivityIndicatorView(activityIndicatorStyle: .Gray) }, didLoadBlock: nil) + super.init(viewBlock: { UIActivityIndicatorView(activityIndicatorStyle: .gray) }, didLoad: nil) preferredFrameSize.height = 32 } - override public func didLoad() { + override open func didLoad() { super.didLoad() activityIndicatorView.startAnimating() } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/Indicators/MessageSentIndicator.swift b/nMessenger/Source/MessageNodes/Indicators/MessageSentIndicator.swift index 801b61c..2bd0d4c 100755 --- a/nMessenger/Source/MessageNodes/Indicators/MessageSentIndicator.swift +++ b/nMessenger/Source/MessageNodes/Indicators/MessageSentIndicator.swift @@ -15,17 +15,17 @@ import UIKit /** Spinning loading indicator class. Used by the NMessenger prefetch. */ -public class MessageSentIndicator: GeneralMessengerCell { +open class MessageSentIndicator: GeneralMessengerCell { /** Horizontal spacing between text and spinner. Defaults to 20.*/ - public var contentPadding:CGFloat = 20 { + open var contentPadding:CGFloat = 20 { didSet { self.setNeedsLayout() } } /** Loading text node*/ - public let text = ASTextNode() + open let text = ASTextNode() /** Sets the loading attributed text for the spinner. Defaults to *"Loading..."* */ - public var messageSentAttributedText:NSAttributedString? { + open var messageSentAttributedText:NSAttributedString? { set { text.attributedString = newValue self.setNeedsLayout() @@ -33,13 +33,13 @@ public class MessageSentIndicator: GeneralMessengerCell { return text.attributedText } } - public var messageSentText: String? { + open var messageSentText: String? { set { text.attributedString = NSAttributedString( string: newValue != nil ? newValue! : "", attributes: [ - NSFontAttributeName: UIFont.systemFontOfSize(14), - NSForegroundColorAttributeName: UIColor.lightGrayColor(), + NSFontAttributeName: UIFont.systemFont(ofSize: 14), + NSForegroundColorAttributeName: UIColor.lightGray, NSKernAttributeName: -0.3 ]) self.setNeedsLayout() @@ -53,14 +53,14 @@ public class MessageSentIndicator: GeneralMessengerCell { addSubnode(text) } - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { let stackLayout = ASStackLayoutSpec( - direction: .Horizontal, + direction: .horizontal, spacing: contentPadding, - justifyContent: .Center, - alignItems: .Center, + justifyContent: .center, + alignItems: .center, children: [ text ]) let paddingLayout = ASInsetLayoutSpec(insets: cellPadding, child: stackLayout) return paddingLayout } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/MessageCell/MessageCellProtocol.swift b/nMessenger/Source/MessageNodes/MessageCell/MessageCellProtocol.swift index 24b415f..5e6c3b3 100755 --- a/nMessenger/Source/MessageNodes/MessageCell/MessageCellProtocol.swift +++ b/nMessenger/Source/MessageNodes/MessageCell/MessageCellProtocol.swift @@ -13,5 +13,5 @@ import Foundation /** Called when the avatar is clicked. Notifies the delegate of the message cell whose avatar is clicked */ - optional func avatarClicked(messageCell: GeneralMessengerCell) -} \ No newline at end of file + @objc optional func avatarClicked(_ messageCell: GeneralMessengerCell) +} diff --git a/nMessenger/Source/MessageNodes/MessageCell/MessageGroup.swift b/nMessenger/Source/MessageNodes/MessageCell/MessageGroup.swift index 049d30c..ceebf42 100755 --- a/nMessenger/Source/MessageNodes/MessageCell/MessageGroup.swift +++ b/nMessenger/Source/MessageNodes/MessageCell/MessageGroup.swift @@ -15,33 +15,33 @@ import AsyncDisplayKit /** Holds a group of messages. Extends GeneralMessengerCell. */ -public class MessageGroup: GeneralMessengerCell { +open class MessageGroup: GeneralMessengerCell { /** Used for current state of new/old messages*/ public enum MessageGroupState { - case Added - case Removed - case Replaced - case None + case added + case removed + case replaced + case none } // MARK: Public Variables - public var delegate: MessageCellProtocol? + open var delegate: MessageCellProtocol? /** Holds a table of GeneralMessengerCells*/ - public private(set) var messageTable = ASTableNode(style: .Plain) + open fileprivate(set) var messageTable = ASTableNode(style: .plain) /** Set to true when the after the component has laid out for the first time*/ - public private(set) var hasLaidOut = false + open fileprivate(set) var hasLaidOut = false /** Data set for messages in the group */ - public private(set) var messages = [GeneralMessengerCell]() + open fileprivate(set) var messages = [GeneralMessengerCell]() /** Delay before add/remove animation begins*/ - public var animationDelay: NSTimeInterval = 0 + open var animationDelay: TimeInterval = 0 /** Avatar new message animation speed */ - public var avatarAnimationSpeed: NSTimeInterval = 0.15 + open var avatarAnimationSpeed: TimeInterval = 0.15 /** Spacing around the avatar */ - public var avatarInsets: UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10) { + open var avatarInsets: UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10) { didSet { self.setNeedsLayout() } @@ -50,14 +50,14 @@ public class MessageGroup: GeneralMessengerCell { /** Message offset spacing from the edge (avatar or messenger bounds) */ - public var messageOffset: CGFloat = 10 { + open var messageOffset: CGFloat = 10 { didSet { self.setNeedsLayout() } } /** ASDisplayNode as the avatar of the cell*/ - public var avatarNode: ASDisplayNode? + open var avatarNode: ASDisplayNode? { willSet{ if let avatarNode = newValue { @@ -78,7 +78,7 @@ public class MessageGroup: GeneralMessengerCell { } /** Bool if the cell is an incoming or out going message cell*/ - public override var isIncomingMessage:Bool { + open override var isIncomingMessage:Bool { didSet { for message in messages { if let message = message as? MessageNode { @@ -90,13 +90,13 @@ public class MessageGroup: GeneralMessengerCell { //MARK: Private variables /** Layout completion block for adding/removing messages*/ - private var layoutCompletionBlock: (()->Void)? + fileprivate var layoutCompletionBlock: (()->Void)? /** Current state of new/old messages*/ - private var state: MessageGroupState? + fileprivate var state: MessageGroupState? /** Default animation delay time for ASTableView*/ - private let tableviewAnimationDelay:NSTimeInterval = 0.3 + fileprivate let tableviewAnimationDelay:TimeInterval = 0.3 /** Button node to handle avatar click*/ - private var avatarButtonNode: ASControlNode = ASControlNode() + fileprivate var avatarButtonNode: ASControlNode = ASControlNode() //MARK: Initializers @@ -107,21 +107,21 @@ public class MessageGroup: GeneralMessengerCell { } /** Initializes the ASTableNode for a group of messages*/ - private func setupTable() { - self.messageTable.delegate = self - self.messageTable.dataSource = self + fileprivate func setupTable() { + self.messageTable?.delegate = self + self.messageTable?.dataSource = self - self.messageTable.view.separatorStyle = .None - self.messageTable.view.scrollEnabled = false - self.messageTable.view.showsVerticalScrollIndicator = false + self.messageTable?.view.separatorStyle = .none + self.messageTable?.view.isScrollEnabled = false + self.messageTable?.view.showsVerticalScrollIndicator = false - self.addSubnode(self.messageTable) + self.addSubnode(self.messageTable!) } /** Creates a listener for the avatar button */ - private func setupAvatarButton() { - self.avatarButtonNode.addTarget(self, action: #selector(MessageGroup.avatarClicked), forControlEvents: .TouchUpInside) - self.avatarButtonNode.exclusiveTouch = true + fileprivate func setupAvatarButton() { + self.avatarButtonNode.addTarget(self, action: #selector(MessageGroup.avatarClicked), forControlEvents: .touchUpInside) + self.avatarButtonNode.isExclusiveTouch = true } // MARK: Override AsycDisaplyKit Methods @@ -129,10 +129,10 @@ public class MessageGroup: GeneralMessengerCell { /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { var tableWidth:CGFloat = 0 - let justifyLocation = isIncomingMessage ? ASStackLayoutJustifyContent.Start : ASStackLayoutJustifyContent.End + let justifyLocation = isIncomingMessage ? ASStackLayoutJustifyContent.start : ASStackLayoutJustifyContent.end //make a space for the avatar if needed if let avatarNode = self.avatarNode { @@ -146,13 +146,13 @@ public class MessageGroup: GeneralMessengerCell { //get the size of every message in the group to calculate height for message in messages { - let newSize = ASSizeRange(min: constrainedSize.min, max: CGSizeMake(tableWidth, constrainedSize.max.height)) - let size = message.measureWithSizeRange(newSize).size + let newSize = ASSizeRange(min: constrainedSize.min, max: CGSize(width: tableWidth, height: constrainedSize.max.height)) + let size = message.measure(with: newSize).size elementHeight += size.height } - self.messageTable.preferredFrameSize = CGSizeMake(tableWidth, elementHeight) + self.messageTable?.preferredFrameSize = CGSize(width: tableWidth, height: elementHeight) - var retLayout:ASLayoutSpec = ASStaticLayoutSpec(children: [self.messageTable]) + var retLayout:ASLayoutSpec = ASStaticLayoutSpec(children: [self.messageTable!]) var stackLayout: ASStackLayoutSpec? var insetLayout: ASInsetLayoutSpec? @@ -171,12 +171,12 @@ public class MessageGroup: GeneralMessengerCell { //layout horizontal stack let cellOrientation = self.isIncomingMessage ? [ins, retLayout] : [retLayout, ins] - stackLayout = ASStackLayoutSpec(direction: .Horizontal, spacing: 0, justifyContent: justifyLocation, alignItems: .End, children: cellOrientation) + stackLayout = ASStackLayoutSpec(direction: .horizontal, spacing: 0, justifyContent: justifyLocation, alignItems: .end, children: cellOrientation) retLayout = stackLayout! } let cellOrientation = self.isIncomingMessage ? [spacer, retLayout] : [retLayout, spacer] - stackLayout = ASStackLayoutSpec(direction: .Horizontal, spacing: self.messageOffset, justifyContent: justifyLocation, alignItems: .End, children: cellOrientation) + stackLayout = ASStackLayoutSpec(direction: .horizontal, spacing: self.messageOffset, justifyContent: justifyLocation, alignItems: .end, children: cellOrientation) insetLayout = ASInsetLayoutSpec(insets: self.cellPadding, child: stackLayout!) return insetLayout! @@ -185,17 +185,17 @@ public class MessageGroup: GeneralMessengerCell { /** Overriding animateLayoutTransition to animate add/remove transitions */ - override public func animateLayoutTransition(context: ASContextTransitioning) { + override open func animateLayoutTransition(_ context: ASContextTransitioning) { if let state = self.state { switch(state) { - case .Added: + case .added: if let _ = self.avatarNode { - self.avatarNode?.frame = context.initialFrameForNode(self.avatarNode!) + self.avatarNode?.frame = context.initialFrame(for: self.avatarNode!) } - UIView.animateWithDuration(self.avatarAnimationSpeed, delay: self.tableviewAnimationDelay + self.animationDelay, options: [], animations: { + UIView.animate(withDuration: self.avatarAnimationSpeed, delay: self.tableviewAnimationDelay + self.animationDelay, options: [], animations: { if let _ = self.avatarNode { - self.avatarNode?.frame = context.finalFrameForNode(self.avatarNode!) + self.avatarNode?.frame = context.finalFrame(for: self.avatarNode!) } }) { (finished) in //complete transition @@ -203,25 +203,26 @@ public class MessageGroup: GeneralMessengerCell { } //wait for layout animation - dispatch_after(dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), Int64(self.animationDelay)*1000 * Int64(NSEC_PER_MSEC)), dispatch_get_main_queue()) { + let dispatchTime: DispatchTime = DispatchTime.now() + Double(Int64(self.animationDelay)*1000 * Int64(NSEC_PER_MSEC)) / Double(NSEC_PER_SEC) + DispatchQueue.main.asyncAfter(deadline: dispatchTime) { //layout to reflect changes self.setNeedsLayout() - let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), Int64(self.tableviewAnimationDelay)*1000 * Int64(NSEC_PER_MSEC)) - dispatch_after(time, dispatch_get_main_queue()) { - let tableView = self.messageTable.view - tableView.endUpdates() + let time: DispatchTime = DispatchTime.now() + Double(Int64(self.tableviewAnimationDelay)*1000 * Int64(NSEC_PER_MSEC)) / Double(NSEC_PER_SEC) + DispatchQueue.main.asyncAfter(deadline: time) { + let tableView = self.messageTable?.view + tableView?.endUpdates() self.callLayoutCompletionBlock() } } break - case .Removed: + case .removed: if let _ = self.avatarNode { - self.avatarNode?.frame = context.initialFrameForNode(self.avatarNode!) + self.avatarNode?.frame = context.initialFrame(for: self.avatarNode!) } - UIView.animateWithDuration(self.tableviewAnimationDelay, delay: 0, options: [], animations: { + UIView.animate(withDuration: self.tableviewAnimationDelay, delay: 0, options: [], animations: { if let _ = self.avatarNode { - self.avatarNode?.frame = context.finalFrameForNode(self.avatarNode!) + self.avatarNode?.frame = context.finalFrame(for: self.avatarNode!) } }) { (finished) in //call completion block and reset @@ -230,14 +231,14 @@ public class MessageGroup: GeneralMessengerCell { context.completeTransition(finished) } break - case .Replaced: + case .replaced: if let _ = self.avatarNode { - self.avatarNode?.frame = context.initialFrameForNode(self.avatarNode!) + self.avatarNode?.frame = context.initialFrame(for: self.avatarNode!) } - UIView.animateWithDuration(self.avatarAnimationSpeed, delay: self.tableviewAnimationDelay, options: [], animations: { + UIView.animate(withDuration: self.avatarAnimationSpeed, delay: self.tableviewAnimationDelay, options: [], animations: { if let _ = self.avatarNode { - self.avatarNode?.frame = context.finalFrameForNode(self.avatarNode!) + self.avatarNode?.frame = context.finalFrame(for: self.avatarNode!) } }) { (finished) in //complete transition @@ -246,10 +247,10 @@ public class MessageGroup: GeneralMessengerCell { //layout to reflect changes self.setNeedsLayout() - let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), Int64(self.tableviewAnimationDelay)*1000 * Int64(NSEC_PER_MSEC)) - dispatch_after(time, dispatch_get_main_queue()) { - let tableView = self.messageTable.view - tableView.endUpdates() + let time: DispatchTime = DispatchTime.now() + Double(Int64(self.tableviewAnimationDelay)*1000 * Int64(NSEC_PER_MSEC)) / Double(NSEC_PER_SEC) + DispatchQueue.main.asyncAfter(deadline: time) { + let tableView = self.messageTable?.view + tableView?.endUpdates() self.callLayoutCompletionBlock() } @@ -264,7 +265,7 @@ public class MessageGroup: GeneralMessengerCell { /** Overriding layoutDidFinish to flag first layout */ - override public func layoutDidFinish() { + override open func layoutDidFinish() { super.layoutDidFinish() self.hasLaidOut = true } @@ -276,22 +277,22 @@ public class MessageGroup: GeneralMessengerCell { - parameter message: the message to add - parameter layoutCompletionBlock: The block to be called once the new node has been added */ - public func addMessageToGroup(message: GeneralMessengerCell, completion: (()->Void)?) { + open func addMessageToGroup(_ message: GeneralMessengerCell, completion: (()->Void)?) { self.updateMessage(message) self.layoutCompletionBlock = completion //if the component is already on the screen if self.hasLaidOut { //set state - self.state = .Added + self.state = .added //update table - let tableView = self.messageTable.view - tableView.beginUpdates() - let indexPath = NSIndexPath(forRow: self.messages.count, inSection:0) + let tableView = self.messageTable?.view + tableView?.beginUpdates() + let indexPath = IndexPath(row: self.messages.count, section:0) self.messages.append(message) - tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + tableView?.insertRows(at: [indexPath], with: .fade) //transition avatar + tableview cells - self.transitionLayoutWithAnimation(true, shouldMeasureAsync: false, measurementCompletion: nil) + self.transitionLayout(withAnimation: true, shouldMeasureAsync: false, measurementCompletion: nil) } else { self.messages.append(message) } @@ -303,9 +304,9 @@ public class MessageGroup: GeneralMessengerCell { - parameter withMessage: The message that will replace the old one - parameter layoutCompletionBlock: The block to be called once the old node has been replaced */ - public func replaceMessage(message: GeneralMessengerCell, withMessage newMessage: GeneralMessengerCell, completion: (()->Void)?) { + open func replaceMessage(_ message: GeneralMessengerCell, withMessage newMessage: GeneralMessengerCell, completion: (()->Void)?) { if self.messages.contains(message) { - if let index = self.messages.indexOf(message) { + if let index = self.messages.index(of: message) { self.updateMessage(newMessage) self.layoutCompletionBlock = completion message.currentTableNode = nil @@ -313,19 +314,19 @@ public class MessageGroup: GeneralMessengerCell { //make sure the group has been laid out so that animations will work if self.hasLaidOut { //set state - self.state = .Replaced + self.state = .replaced //update table - let tableView = self.messageTable.view - tableView.beginUpdates() + let tableView = self.messageTable?.view + tableView?.beginUpdates() self.messages[index] = newMessage - let indexPath = NSIndexPath(forRow: index, inSection:0) - tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + let indexPath = IndexPath(row: index, section:0) + tableView?.reloadRows(at: [indexPath], with: .fade) - let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), Int64(self.animationDelay)*1000 * Int64(NSEC_PER_MSEC)) - dispatch_after(time, dispatch_get_main_queue()) { - tableView.endUpdatesAnimated(true, completion: { (done) in - self.transitionLayoutWithAnimation(true, shouldMeasureAsync: false, measurementCompletion:nil) + let time: DispatchTime = DispatchTime.now() + Double(Int64(self.animationDelay)*1000 * Int64(NSEC_PER_MSEC)) / Double(NSEC_PER_SEC) + DispatchQueue.main.asyncAfter(deadline: time) { + tableView?.endUpdates(animated: true, completion: { (done) in + self.transitionLayout(withAnimation: true, shouldMeasureAsync: false, measurementCompletion:nil) }) } } else { //replace message @@ -340,10 +341,10 @@ public class MessageGroup: GeneralMessengerCell { - parameter message: the message to remove - parameter layoutCompletionBlock: The block to be called once the new node has been removed */ - public func removeMessageFromGroup(message: GeneralMessengerCell, completion: (()->Void)?) { + open func removeMessageFromGroup(_ message: GeneralMessengerCell, completion: (()->Void)?) { if self.messages.contains(message) { - if let index = self.messages.indexOf(message) { + if let index = self.messages.index(of: message) { let isLastMessage = self.messages.last == message self.layoutCompletionBlock = completion message.currentTableNode = nil @@ -351,34 +352,34 @@ public class MessageGroup: GeneralMessengerCell { //make sure the group has been laid out so that animations will work if self.hasLaidOut { //set state - self.state = .Removed + self.state = .removed //update table - let tableView = self.messageTable.view - tableView.beginUpdates() - self.messages.removeAtIndex(index) - let indexPath = NSIndexPath(forRow: index, inSection:0) - tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade) + let tableView = self.messageTable?.view + tableView?.beginUpdates() + self.messages.remove(at: index) + let indexPath = IndexPath(row: index, section:0) + tableView?.deleteRows(at: [indexPath], with: .fade) //use a special animation if it is the last message if isLastMessage && self.avatarNode != nil { - UIView.animateWithDuration(self.avatarAnimationSpeed, delay: self.animationDelay, options: [], animations: { + UIView.animate(withDuration: self.avatarAnimationSpeed, delay: self.animationDelay, options: [], animations: { if let avatarNode = self.avatarNode { - avatarNode.frame.origin.y = self.messageTable.view.rectForRowAtIndexPath(NSIndexPath(forItem: index-1, inSection: 0)).maxY - avatarNode.frame.height + self.cellPadding.top + avatarNode.frame.origin.y = (self.messageTable?.view.rectForRow(at: IndexPath(item: index-1, section: 0)).maxY)! - avatarNode.frame.height + self.cellPadding.top } }, completion: nil) } let extraDelay = isLastMessage && self.avatarNode != nil ? self.avatarAnimationSpeed : 0 - let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), Int64(extraDelay + self.animationDelay)*1000 * Int64(NSEC_PER_MSEC)) - dispatch_after(time, dispatch_get_main_queue()) { - tableView.endUpdatesAnimated(true, completion: { (done) in - self.transitionLayoutWithAnimation(true, shouldMeasureAsync: false, measurementCompletion:nil) + let time: DispatchTime = DispatchTime.now() + Double(Int64(extraDelay + self.animationDelay)*1000 * Int64(NSEC_PER_MSEC)) / Double(NSEC_PER_SEC) + DispatchQueue.main.asyncAfter(deadline: time) { + tableView?.endUpdates(animated: true, completion: { (done) in + self.transitionLayout(withAnimation: true, shouldMeasureAsync: false, measurementCompletion:nil) }) } } else { //message shouldn't be in this group - self.messages.removeAtIndex(index) + self.messages.remove(at: index) } } } @@ -390,12 +391,12 @@ public class MessageGroup: GeneralMessengerCell { Updates message UI features to reflect sender. These features are pulled from the message configuration. Also updates *currentTableNode* property to the message group's table - parameter message: the message to update */ - private func updateMessage(message: GeneralMessengerCell) { + fileprivate func updateMessage(_ message: GeneralMessengerCell) { message.currentTableNode = self.messageTable //message specific UI if messages.first == nil { //will be the first message - message.cellPadding = UIEdgeInsetsZero + message.cellPadding = UIEdgeInsets.zero if let message = message as? MessageNode { message.contentNode?.backgroundBubble = message.contentNode?.bubbleConfiguration.getBubble() message.isIncomingMessage = self.isIncomingMessage @@ -415,8 +416,8 @@ public class MessageGroup: GeneralMessengerCell { /** Calls and resets the layout completion block */ - private func callLayoutCompletionBlock() { - self.state = .None + fileprivate func callLayoutCompletionBlock() { + self.state = .none self.layoutCompletionBlock?() self.layoutCompletionBlock = nil } @@ -435,15 +436,15 @@ extension MessageGroup { /** TableView functions extension */ extension MessageGroup: ASTableDelegate, ASTableDataSource { - public func numberOfSectionsInTableView(tableView: UITableView) -> Int { + public func numberOfSections(in tableView: UITableView) -> Int { return 1 } - public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return messages.count } - public func tableView(tableView: ASTableView, nodeForRowAtIndexPath indexPath: NSIndexPath) -> ASCellNode { - return messages[indexPath.row] + public func tableView(_ tableView: ASTableView, nodeForRowAt indexPath: IndexPath) -> ASCellNode { + return messages[(indexPath as NSIndexPath).row] } -} \ No newline at end of file +} diff --git a/nMessenger/Source/MessageNodes/MessageCell/MessageNode.swift b/nMessenger/Source/MessageNodes/MessageCell/MessageNode.swift index 7860489..1442334 100755 --- a/nMessenger/Source/MessageNodes/MessageCell/MessageNode.swift +++ b/nMessenger/Source/MessageNodes/MessageCell/MessageNode.swift @@ -15,13 +15,13 @@ import AsyncDisplayKit /** Base message class for N Messenger. Extends GeneralMessengerCell. Holds one message */ -public class MessageNode: GeneralMessengerCell { +open class MessageNode: GeneralMessengerCell { // MARK: Public Variables - public var delegate: MessageCellProtocol? + open var delegate: MessageCellProtocol? /** ASDisplayNode as the content of the cell*/ - public var contentNode: ContentNode? + open var contentNode: ContentNode? { willSet{ if let contentNode = newValue { @@ -40,7 +40,7 @@ public class MessageNode: GeneralMessengerCell { } /** ASDisplayNode as the avatar of the cell*/ - public var avatarNode: ASDisplayNode? + open var avatarNode: ASDisplayNode? { willSet{ if let avatarNode = newValue { @@ -59,7 +59,7 @@ public class MessageNode: GeneralMessengerCell { } /** ASDisplayNode as the header of the cell*/ - public var headerNode: ASDisplayNode? + open var headerNode: ASDisplayNode? { willSet{ if let headerNode = newValue { @@ -77,7 +77,7 @@ public class MessageNode: GeneralMessengerCell { } /** ASDisplayNode as the footer of the cell*/ - public var footerNode: ASDisplayNode? { + open var footerNode: ASDisplayNode? { willSet{ if let footerNode = newValue { if let oldFooter = self.footerNode { @@ -96,35 +96,35 @@ public class MessageNode: GeneralMessengerCell { /** Spacing around the avatar. Defaults to UIEdgeInsetsMake(0, 0, 0, 10) */ - public var avatarInsets: UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10) { + open var avatarInsets: UIEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10) { didSet { self.setNeedsLayout() } } /** Message offset from edge (edge->offset->message content). Defaults to 10*/ - public var messageOffset: CGFloat = 10 { + open var messageOffset: CGFloat = 10 { didSet { self.setNeedsLayout() } } /** Spacing under the header. Defaults to 10*/ - public var headerSpacing: CGFloat = 10 { + open var headerSpacing: CGFloat = 10 { didSet { self.setNeedsLayout() } } /** Spacing above the footer. Defaults to 10*/ - public var footerSpacing: CGFloat = 10 { + open var footerSpacing: CGFloat = 10 { didSet { self.setNeedsLayout() } } /** Bool if the cell is an incoming or out going message cell*/ - public override var isIncomingMessage:Bool { + open override var isIncomingMessage:Bool { didSet { self.contentNode?.isIncomingMessage = isIncomingMessage } @@ -132,7 +132,7 @@ public class MessageNode: GeneralMessengerCell { // MARK: Private Variables /** Button node to handle avatar click*/ - private var avatarButtonNode: ASControlNode = ASControlNode() + fileprivate var avatarButtonNode: ASControlNode = ASControlNode() // MARK: Initializers @@ -150,11 +150,11 @@ public class MessageNode: GeneralMessengerCell { /** Creates background node and avatar node if they do not exist */ - private func setupMessageNode(withContent content: ContentNode) + fileprivate func setupMessageNode(withContent content: ContentNode) { - self.avatarButtonNode.addTarget(self, action: #selector(MessageNode.avatarClicked), forControlEvents: .TouchUpInside) - self.avatarButtonNode.exclusiveTouch = true + self.avatarButtonNode.addTarget(self, action: #selector(MessageNode.avatarClicked), forControlEvents: .touchUpInside) + self.avatarButtonNode.isExclusiveTouch = true self.contentNode = content @@ -165,12 +165,12 @@ public class MessageNode: GeneralMessengerCell { /** Overriding layoutSpecThatFits to specifiy relatiohsips between elements in the cell */ - override public func layoutSpecThatFits(constrainedSize: ASSizeRange) -> ASLayoutSpec { + override open func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec { var layoutSpecs: ASLayoutSpec! let spacer = ASLayoutSpec() //location dependent on sender - let justifyLocation = isIncomingMessage ? ASStackLayoutJustifyContent.Start : ASStackLayoutJustifyContent.End + let justifyLocation = isIncomingMessage ? ASStackLayoutJustifyContent.start : ASStackLayoutJustifyContent.end if let tmpAvatar = self.avatarNode { let tmpSizeMesuare = tmpAvatar.measure(constrainedSize.max) @@ -179,7 +179,7 @@ public class MessageNode: GeneralMessengerCell { let avatarButtonSizeLayout = ASStaticLayoutSpec(children: [self.avatarButtonNode]) let avatarBackStack = ASBackgroundLayoutSpec(child: avatarButtonSizeLayout, background: avatarSizeLayout) let width = constrainedSize.max.width - tmpSizeMesuare.width - self.cellPadding.left - self.cellPadding.right - avatarInsets.left - avatarInsets.right - self.messageOffset - let tmpSizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(width),ASRelativeDimensionMakeWithPercent(1))) + let tmpSizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSize.zero), ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(width),ASRelativeDimensionMakeWithPercent(1))) self.contentNode!.sizeRange = tmpSizeRange let contentSizeLayout = ASStaticLayoutSpec(children: [self.contentNode!]) @@ -187,29 +187,29 @@ public class MessageNode: GeneralMessengerCell { let cellOrientation = isIncomingMessage ? [ins, contentSizeLayout] : [contentSizeLayout,ins] - layoutSpecs = ASStackLayoutSpec(direction: .Horizontal, spacing: 0, justifyContent: justifyLocation, alignItems: .End, children: cellOrientation) + layoutSpecs = ASStackLayoutSpec(direction: .horizontal, spacing: 0, justifyContent: justifyLocation, alignItems: .end, children: cellOrientation) contentSizeLayout.flexShrink = true } else { let width = constrainedSize.max.width - self.cellPadding.left - self.cellPadding.right - self.messageOffset - let tmpSizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSizeZero), ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(width),ASRelativeDimensionMakeWithPercent(1))) + let tmpSizeRange = ASRelativeSizeRangeMake(ASRelativeSizeMakeWithCGSize(CGSize.zero), ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(width),ASRelativeDimensionMakeWithPercent(1))) self.contentNode!.sizeRange = tmpSizeRange let contentSizeLayout = ASStaticLayoutSpec(children: [self.contentNode!]) - layoutSpecs = ASStackLayoutSpec(direction: .Horizontal, spacing: 0, justifyContent: justifyLocation, alignItems: .End, children: [spacer, contentSizeLayout]) + layoutSpecs = ASStackLayoutSpec(direction: .horizontal, spacing: 0, justifyContent: justifyLocation, alignItems: .end, children: [spacer, contentSizeLayout]) contentSizeLayout.flexShrink = true } if let headerNode = self.headerNode { - layoutSpecs = ASStackLayoutSpec(direction: .Vertical, spacing: self.headerSpacing, justifyContent: .Start, alignItems: isIncomingMessage ? .Start : .End, children: [headerNode, layoutSpecs]) + layoutSpecs = ASStackLayoutSpec(direction: .vertical, spacing: self.headerSpacing, justifyContent: .start, alignItems: isIncomingMessage ? .start : .end, children: [headerNode, layoutSpecs]) } if let footerNode = self.footerNode { - layoutSpecs = ASStackLayoutSpec(direction: .Vertical, spacing: self.footerSpacing, justifyContent: .Start, alignItems: isIncomingMessage ? .Start : .End, children: [layoutSpecs, footerNode]) + layoutSpecs = ASStackLayoutSpec(direction: .vertical, spacing: self.footerSpacing, justifyContent: .start, alignItems: isIncomingMessage ? .start : .end, children: [layoutSpecs, footerNode]) } let cellOrientation = self.isIncomingMessage ? [spacer, layoutSpecs!] : [layoutSpecs!, spacer] - layoutSpecs = ASStackLayoutSpec(direction: .Horizontal, spacing: self.messageOffset, justifyContent: justifyLocation, alignItems: .End, children: cellOrientation) + layoutSpecs = ASStackLayoutSpec(direction: .horizontal, spacing: self.messageOffset, justifyContent: justifyLocation, alignItems: .end, children: cellOrientation) layoutSpecs = ASInsetLayoutSpec(insets: self.cellPadding, child: layoutSpecs) return layoutSpecs } @@ -220,7 +220,7 @@ public class MessageNode: GeneralMessengerCell { /** Overriding didLoad to add UILongPressGestureRecognizer to view */ - override public func didLoad() { + override open func didLoad() { super.didLoad() let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(messageNodeLongPressSelector(_:))) @@ -230,36 +230,36 @@ public class MessageNode: GeneralMessengerCell { /** Overriding canBecomeFirstResponder to make cell first responder */ - override public func canBecomeFirstResponder() -> Bool { + override open func canBecomeFirstResponder() -> Bool { return true } /** Overriding touchesBegan to make to close UIMenuController */ - override public func touchesBegan(touches: Set, withEvent event: UIEvent?) { - super.touchesBegan(touches, withEvent: event) - if UIMenuController.sharedMenuController().menuVisible == true { - UIMenuController.sharedMenuController().setMenuVisible(false, animated: true) + override open func touchesBegan(_ touches: Set, with event: UIEvent?) { + super.touchesBegan(touches, with: event) + if UIMenuController.shared.isMenuVisible == true { + UIMenuController.shared.setMenuVisible(false, animated: true) } } /** Overriding touchesEnded to make to handle events with UIMenuController */ - override public func touchesEnded(touches: Set, withEvent event: UIEvent?) { - super.touchesEnded(touches, withEvent: event) - if UIMenuController.sharedMenuController().menuVisible == false { + override open func touchesEnded(_ touches: Set, with event: UIEvent?) { + super.touchesEnded(touches, with: event) + if UIMenuController.shared.isMenuVisible == false { } } /** Overriding touchesCancelled to make to handle events with UIMenuController */ - override public func touchesCancelled(touches: Set?, withEvent event: UIEvent?) { - super.touchesCancelled(touches, withEvent: event) + override open func touchesCancelled(_ touches: Set?, with event: UIEvent?) { + super.touchesCancelled(touches, with: event) - if UIMenuController.sharedMenuController().menuVisible == false { + if UIMenuController.shared.isMenuVisible == false { } } @@ -272,7 +272,7 @@ public class MessageNode: GeneralMessengerCell { - parameter recognizer: Must be an UITapGestureRecognizer. Can be be overritten when subclassed */ - public func messageNodeLongPressSelector(recognizer: UITapGestureRecognizer) { + open func messageNodeLongPressSelector(_ recognizer: UITapGestureRecognizer) { contentNode?.messageNodeLongPressSelector(recognizer) } } @@ -286,4 +286,4 @@ extension MessageNode { { self.delegate?.avatarClicked?(self) } -} \ No newline at end of file +} diff --git a/nMessenger/Source/Messenger/Components/CameraViewController.swift b/nMessenger/Source/Messenger/Components/CameraViewController.swift index d520388..eebd050 100755 --- a/nMessenger/Source/Messenger/Components/CameraViewController.swift +++ b/nMessenger/Source/Messenger/Components/CameraViewController.swift @@ -20,7 +20,7 @@ public protocol CameraViewDelegate { /** Should define behavior when a photo is selected */ - func pickedImage(image: UIImage!) + func pickedImage(_ image: UIImage!) /** Should define behavior cancel button is tapped */ @@ -32,53 +32,53 @@ public protocol CameraViewDelegate { Defines type of selection the user is making - camera of photo library */ public enum SelectionType { - case Camera - case Library + case camera + case library } //MARK: CameraViewController /** CameraViewController class for NMessenger. Defines the camera view for NMessenger. This is where the user will take photos or select them from the library. */ -public class CameraViewController: UIImagePickerController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { +open class CameraViewController: UIImagePickerController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { //MARK: Public Parameters //CameraViewDelegate that implemets the delegate methods - public var cameraDelegate: CameraViewDelegate! + open var cameraDelegate: CameraViewDelegate! //SelectionType type of selection the user is making - defualt is camera - public var selection = SelectionType.Camera + open var selection = SelectionType.camera //AVAuthorizationStatus authorization status for the camera - public var cameraAuthStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) + open var cameraAuthStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) //PHAuthorizationStatus authorization status for the library - public var photoLibAuthStatus = PHPhotoLibrary.authorizationStatus() + open var photoLibAuthStatus = PHPhotoLibrary.authorizationStatus() //MARK: Private Parameters //UIButton to change to gallery mode - private var gallery: UIButton! + fileprivate var gallery: UIButton! //UIImageView image from the gallery - private var galleryImage: UIImageView! + fileprivate var galleryImage: UIImageView! //UIButton to take a photo - private var capturePictureButton: UIButton! + fileprivate var capturePictureButton: UIButton! //UIButton to flip camera between front and back - private var flipCamera:UIButton! + fileprivate var flipCamera:UIButton! //UIToolbar to hold buttons above the live camera view - private var cameraToolbar: UIToolbar! + fileprivate var cameraToolbar: UIToolbar! //UIButton to enable/disable flash - private var flashButton:UIButton! + fileprivate var flashButton:UIButton! //CGFloat to define size for capture button - private let captureButtonSize:CGFloat = 80 + fileprivate let captureButtonSize:CGFloat = 80 //CGFloat to define size for buttons under the live camera view - private let sideButtonSize:CGFloat = 50 + fileprivate let sideButtonSize:CGFloat = 50 //CGFloat to define padding for bottom view - private let bottomPadding:CGFloat = 40 + fileprivate let bottomPadding:CGFloat = 40 //Bool if user gave permission for the camera - private let isCameraAvailable = UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDevice.Rear) || - UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDevice.Front) + fileprivate let isCameraAvailable = UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDevice.rear) || + UIImagePickerController.isCameraDeviceAvailable(UIImagePickerControllerCameraDevice.front) //MARK: View Lifecycle /** Ovreriding viewDidLoad to setup the controller Calls helper method */ - override public func viewDidLoad() { + override open func viewDidLoad() { super.viewDidLoad() self.allowsEditing = true self.delegate = self @@ -88,10 +88,10 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Ovreriding viewDidAppear to setup the camera view if there are permissions for the camera */ - override public func viewDidAppear(animated: Bool) { + override open func viewDidAppear(_ animated: Bool) { - if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) { - if (self.sourceType == UIImagePickerControllerSourceType.Camera) { + if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)) { + if (self.sourceType == UIImagePickerControllerSourceType.camera) { orientCamera(flipCamera) setFlash(flashButton) } @@ -102,27 +102,27 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Initialise the view and request for permissions if necessary */ - private func initView() { + fileprivate func initView() { //check if the camera is available - if ((UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) && (cameraAuthStatus == AVAuthorizationStatus.Authorized)){ - self.sourceType = UIImagePickerControllerSourceType.Camera + if ((UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera)) && (cameraAuthStatus == AVAuthorizationStatus.authorized)){ + self.sourceType = UIImagePickerControllerSourceType.camera self.showsCameraControls = false - self.selection = SelectionType.Camera + self.selection = SelectionType.camera self.renderCameraElements() } else { - self.cameraAuthStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) - if(photoLibAuthStatus != PHAuthorizationStatus.Authorized) { + self.cameraAuthStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) + if(photoLibAuthStatus != PHAuthorizationStatus.authorized) { self.requestPhotoLibraryPermissions({ (granted) in if(granted) { - self.sourceType = UIImagePickerControllerSourceType.PhotoLibrary - self.selection = SelectionType.Library + self.sourceType = UIImagePickerControllerSourceType.photoLibrary + self.selection = SelectionType.library } else { self.photoLibAuthStatus = PHPhotoLibrary.authorizationStatus() - self.dismissViewControllerAnimated(true, completion: { + self.dismiss(animated: true, completion: { let presentingViewController = self.cameraDelegate as! NMessengerViewController ModalAlertUtilities.postGoToSettingToEnableLibraryModal(fromController: presentingViewController) }) @@ -131,18 +131,18 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl } else { - self.sourceType = UIImagePickerControllerSourceType.PhotoLibrary - self.selection = SelectionType.Library + self.sourceType = UIImagePickerControllerSourceType.photoLibrary + self.selection = SelectionType.library } } } /** Adds all the buttons for the custom camera view */ - private func renderCameraElements() { + fileprivate func renderCameraElements() { addGalleryButton() //set gallery image thumbnail - if(photoLibAuthStatus != PHAuthorizationStatus.Authorized) { + if(photoLibAuthStatus != PHAuthorizationStatus.authorized) { requestPhotoLibraryPermissions({ (granted) in if(granted) { self.getGalleryThumbnail() @@ -173,30 +173,30 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Adds the gallery button for the custom camera view */ - private func addGalleryButton() { + fileprivate func addGalleryButton() { //GALLERY BUTTON - gallery = UIButton(frame: CGRectMake(self.view.frame.width - sideButtonSize - bottomPadding, self.view.frame.height - sideButtonSize - bottomPadding, sideButtonSize, sideButtonSize)) - gallery.addTarget(self, action: #selector(CameraViewController.changePictureMode), forControlEvents: UIControlEvents.TouchUpInside) - gallery.setImage(UIImage(named: "cameraRollIcon", inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil)?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: UIControlState.Normal) - gallery.tintColor = UIColor.whiteColor() + gallery = UIButton(frame: CGRect(x: self.view.frame.width - sideButtonSize - bottomPadding, y: self.view.frame.height - sideButtonSize - bottomPadding, width: sideButtonSize, height: sideButtonSize)) + gallery.addTarget(self, action: #selector(CameraViewController.changePictureMode), for: UIControlEvents.touchUpInside) + gallery.setImage(UIImage(named: "cameraRollIcon", in: Bundle(for: NMessengerViewController.self), compatibleWith: nil)?.withRenderingMode(UIImageRenderingMode.alwaysTemplate), for: UIControlState()) + gallery.tintColor = UIColor.white galleryImage = UIImageView(frame: gallery.frame) - galleryImage.contentMode = UIViewContentMode.ScaleAspectFill + galleryImage.contentMode = UIViewContentMode.scaleAspectFill galleryImage.clipsToBounds = true - galleryImage.hidden = true + galleryImage.isHidden = true } /** Adds the gallery thumbnail for the custom camera view */ - private func getGalleryThumbnail() { + fileprivate func getGalleryThumbnail() { let fetchOptions = PHFetchOptions() fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)] - let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) - let lastAsset = fetchResult.lastObject as! PHAsset + let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions) + let lastAsset = fetchResult.lastObject as PHAsset! let requestOptions = PHImageRequestOptions() - requestOptions.version = PHImageRequestOptionsVersion.Current - PHImageManager.defaultManager().requestImageForAsset(lastAsset, targetSize: self.galleryImage.frame.size, contentMode: PHImageContentMode.AspectFill, options: requestOptions) { (image, info) -> Void in + requestOptions.version = PHImageRequestOptionsVersion.current + PHImageManager.default().requestImage(for: lastAsset!, targetSize: self.galleryImage.frame.size, contentMode: PHImageContentMode.aspectFill, options: requestOptions) { (image, info) -> Void in - dispatch_async(dispatch_get_main_queue(), { () -> Void in + DispatchQueue.main.async(execute: { () -> Void in self.galleryImage.image = image }) } @@ -204,52 +204,52 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Adds the capture button for the custom camera view */ - private func addCaptureButton() { + fileprivate func addCaptureButton() { //CAPTURE BUTTON - capturePictureButton = UIButton(frame: CGRectMake(self.view.frame.width/2 - bottomPadding, self.view.frame.height - captureButtonSize - bottomPadding, captureButtonSize, captureButtonSize)) - capturePictureButton.setImage(UIImage(named: "shutterBtn", inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil)?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: UIControlState.Normal) - capturePictureButton.tintColor = UIColor.whiteColor() + capturePictureButton = UIButton(frame: CGRect(x: self.view.frame.width/2 - bottomPadding, y: self.view.frame.height - captureButtonSize - bottomPadding, width: captureButtonSize, height: captureButtonSize)) + capturePictureButton.setImage(UIImage(named: "shutterBtn", in: Bundle(for: NMessengerViewController.self), compatibleWith: nil)?.withRenderingMode(UIImageRenderingMode.alwaysTemplate), for: UIControlState()) + capturePictureButton.tintColor = UIColor.white //call the uiimagepickercontroller method takePicture() - capturePictureButton.addTarget(self, action: #selector(CameraViewController.capture(_:)), forControlEvents: UIControlEvents.TouchUpInside) + capturePictureButton.addTarget(self, action: #selector(CameraViewController.capture(_:)), for: UIControlEvents.touchUpInside) } /** Adds the flip button for the custom camera view */ - private func addFlipCameraButton() { + fileprivate func addFlipCameraButton() { //FLIP CAMERA BUTTON - flipCamera = UIButton(frame: CGRectMake(bottomPadding, self.view.frame.height - sideButtonSize - bottomPadding, sideButtonSize, sideButtonSize)) - flipCamera.addTarget(self, action: #selector(CameraViewController.flipCamera(_:)), forControlEvents: UIControlEvents.TouchUpInside) - flipCamera.setImage(UIImage(named: "flipCameraIcon", inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil)?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: UIControlState.Normal) - flipCamera.tintColor = UIColor.whiteColor() + flipCamera = UIButton(frame: CGRect(x: bottomPadding, y: self.view.frame.height - sideButtonSize - bottomPadding, width: sideButtonSize, height: sideButtonSize)) + flipCamera.addTarget(self, action: #selector(CameraViewController.flipCamera(_:)), for: UIControlEvents.touchUpInside) + flipCamera.setImage(UIImage(named: "flipCameraIcon", in: Bundle(for: NMessengerViewController.self), compatibleWith: nil)?.withRenderingMode(UIImageRenderingMode.alwaysTemplate), for: UIControlState()) + flipCamera.tintColor = UIColor.white } /** Adds the toolbar for the custom camera view */ - private func addCameraToolBar() { + fileprivate func addCameraToolBar() { //CAMERA TOOLBAR - cameraToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.frame.width, 60)) - cameraToolbar.barStyle = UIBarStyle.BlackTranslucent - cameraToolbar.translucent = true - let exitButton = UIButton(frame: CGRectMake(20, 10, 40, 40)) - exitButton.setImage(UIImage(named: "exitIcon", inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil)?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: UIControlState.Normal) - exitButton.tintColor = UIColor.whiteColor() + cameraToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 60)) + cameraToolbar.barStyle = UIBarStyle.blackTranslucent + cameraToolbar.isTranslucent = true + let exitButton = UIButton(frame: CGRect(x: 20, y: 10, width: 40, height: 40)) + exitButton.setImage(UIImage(named: "exitIcon", in: Bundle(for: NMessengerViewController.self), compatibleWith: nil)?.withRenderingMode(UIImageRenderingMode.alwaysTemplate), for: UIControlState()) + exitButton.tintColor = UIColor.white exitButton.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) - exitButton.addTarget(self, action: #selector(CameraViewController.exitButtonPressed), forControlEvents: UIControlEvents.TouchUpInside) + exitButton.addTarget(self, action: #selector(CameraViewController.exitButtonPressed), for: UIControlEvents.touchUpInside) cameraToolbar.addSubview(exitButton) } /** Adds the flash button for the custom camera view */ - public func addFlashButton() { + open func addFlashButton() { //Flash Button - flashButton = UIButton(frame: CGRectMake(self.view.frame.width - 60, 10, 40, 40)) - flashButton.setImage(UIImage(named: "flashIcon", inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil)?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: UIControlState.Normal) + flashButton = UIButton(frame: CGRect(x: self.view.frame.width - 60, y: 10, width: 40, height: 40)) + flashButton.setImage(UIImage(named: "flashIcon", in: Bundle(for: NMessengerViewController.self), compatibleWith: nil)?.withRenderingMode(UIImageRenderingMode.alwaysTemplate), for: UIControlState()) flashButton.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) - flashButton.tintColor = UIColor.whiteColor() - flashButton.addTarget(self, action: #selector(CameraViewController.toggleFlash(_:)), forControlEvents: UIControlEvents.TouchUpInside) + flashButton.tintColor = UIColor.white + flashButton.addTarget(self, action: #selector(CameraViewController.toggleFlash(_:)), for: UIControlEvents.touchUpInside) cameraToolbar.addSubview(flashButton) } @@ -257,15 +257,26 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Implementing didFinishPickingMediaWithInfo to send the selected image to the cameraDelegate */ - public func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { - var myImage = info[UIImagePickerControllerEditedImage] as? UIImage + open func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { + var myImage:UIImage? = nil + + if let tmpImage = info[UIImagePickerControllerEditedImage] as? UIImage { + myImage = tmpImage + } else{ + print("Something went wrong") + } if myImage == nil { - myImage = info[UIImagePickerControllerOriginalImage] as? UIImage + if let tmpImage = info[UIImagePickerControllerOriginalImage] as? UIImage { + myImage = tmpImage + } else{ + print("Something went wrong") + } + //myImage = info[UIImagePickerControllerOriginalImage] as? UIImage /* Correctly flip the mirrored image of front-facing camera */ - if self.cameraDevice == UIImagePickerControllerCameraDevice.Front { - if let im = myImage, cgImage = im.CGImage { - myImage = UIImage(CGImage: cgImage, scale: im.scale, orientation: UIImageOrientation.LeftMirrored) + if self.cameraDevice == UIImagePickerControllerCameraDevice.front { + if let im = myImage, let cgImage = im.cgImage { + myImage = UIImage(cgImage: cgImage, scale: im.scale, orientation: UIImageOrientation.leftMirrored) } } } @@ -277,12 +288,12 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Implementing imagePickerControllerDidCancel to go back to camera view or close the view */ - public func imagePickerControllerDidCancel(picker: UIImagePickerController) { + open func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { switch selection { - case .Camera where !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) : + case .camera where !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) : cameraDelegate.cameraCancelSelection() - case .Library: + case .library: changePictureMode() default: break @@ -293,17 +304,17 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Changes between camera view and gallery view */ - public func changePictureMode() { + open func changePictureMode() { switch selection { - case .Camera: - selection = SelectionType.Library + case .camera: + selection = SelectionType.library removeCameraElements() - self.sourceType = UIImagePickerControllerSourceType.PhotoLibrary - case .Library where (isCameraAvailable && (cameraAuthStatus == AVAuthorizationStatus.Authorized)): - selection = SelectionType.Camera + self.sourceType = UIImagePickerControllerSourceType.photoLibrary + case .library where (isCameraAvailable && (cameraAuthStatus == AVAuthorizationStatus.authorized)): + selection = SelectionType.camera addCameraElements() - self.sourceType = UIImagePickerControllerSourceType.Camera + self.sourceType = UIImagePickerControllerSourceType.camera orientCamera(flipCamera) setFlash(flashButton) default: @@ -313,8 +324,8 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Adds buttons for the camera view */ - private func addCameraElements() { - if (self.selection == SelectionType.Camera) { + fileprivate func addCameraElements() { + if (self.selection == SelectionType.camera) { self.view.addSubview(galleryImage) self.view.addSubview(gallery) self.view.addSubview(flipCamera) @@ -325,8 +336,8 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Removes from the camera view */ - private func removeCameraElements() { - if (self.selection != SelectionType.Camera) { + fileprivate func removeCameraElements() { + if (self.selection != SelectionType.camera) { galleryImage.removeFromSuperview() gallery.removeFromSuperview() flipCamera.removeFromSuperview() @@ -337,59 +348,59 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl /** Closes the view */ - public func exitButtonPressed() { + open func exitButtonPressed() { cameraDelegate.cameraCancelSelection() } /** Takes a photo */ - public func capture(sender: UIButton) { + open func capture(_ sender: UIButton) { self.takePicture() } /** Enables/disables flash */ - public func toggleFlash(sender: UIButton) { - if (sender.selected == false) { + open func toggleFlash(_ sender: UIButton) { + if (sender.isSelected == false) { sender.tintColor = UIColor.n1ActionBlueColor() - sender.selected = true + sender.isSelected = true } else { - sender.tintColor = UIColor.whiteColor() - sender.selected = false + sender.tintColor = UIColor.white + sender.isSelected = false } setFlash(sender) } /** Enables/disables flash */ - private func setFlash(sender: UIButton) { - if (sender.selected == true) { - self.cameraFlashMode = UIImagePickerControllerCameraFlashMode.On + fileprivate func setFlash(_ sender: UIButton) { + if (sender.isSelected == true) { + self.cameraFlashMode = UIImagePickerControllerCameraFlashMode.on } else { - self.cameraFlashMode = UIImagePickerControllerCameraFlashMode.Off + self.cameraFlashMode = UIImagePickerControllerCameraFlashMode.off } } /** Changes the camera from front to back */ - public func flipCamera(sender: UIButton) { - if (sender.selected == false) { + open func flipCamera(_ sender: UIButton) { + if (sender.isSelected == false) { sender.tintColor = UIColor.n1ActionBlueColor() - sender.selected = true + sender.isSelected = true } else { - sender.tintColor = UIColor.whiteColor() - sender.selected = false + sender.tintColor = UIColor.white + sender.isSelected = false } orientCamera(sender) } /** Changes the camera from front to back */ - private func orientCamera(sender:UIButton) { - if (sender.selected == true) { - self.cameraDevice = UIImagePickerControllerCameraDevice.Front + fileprivate func orientCamera(_ sender:UIButton) { + if (sender.isSelected == true) { + self.cameraDevice = UIImagePickerControllerCameraDevice.front } else { - self.cameraDevice = UIImagePickerControllerCameraDevice.Rear + self.cameraDevice = UIImagePickerControllerCameraDevice.rear } } @@ -398,18 +409,18 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl Requests access for the camera and calls completion block - parameter completion: Must be (granted : Bool) -> Void */ - public func isCameraPermissionGranted(completion:(granted : Bool) -> Void) { + open func isCameraPermissionGranted(_ completion:@escaping (_ granted : Bool) -> Void) { requestAccessForCamera({ (granted) in - completion(granted: granted) + completion(granted) }) } /** Requests access for the camera and calls completion block - parameter completion: Must be (granted : Bool) -> Void */ - public func requestAccessForCamera(completion:(granted : Bool) -> Void) { - AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo) { (granted) in - completion(granted: granted) + open func requestAccessForCamera(_ completion:@escaping (_ granted : Bool) -> Void) { + AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { (granted) in + completion(granted) } } @@ -418,12 +429,12 @@ public class CameraViewController: UIImagePickerController, UIImagePickerControl Requests access for the library and calls completion block - parameter completion: Must be (granted : Bool) -> Void */ - public func requestPhotoLibraryPermissions(completion: (granted : Bool) -> Void) { + open func requestPhotoLibraryPermissions(_ completion: @escaping (_ granted : Bool) -> Void) { PHPhotoLibrary.requestAuthorization { status in switch status { - case .Authorized: completion(granted : true) - case .Denied, .NotDetermined, .Restricted : completion(granted : false) + case .authorized: completion(true) + case .denied, .notDetermined, .restricted : completion(false) } } } -} \ No newline at end of file +} diff --git a/nMessenger/Source/Messenger/Components/InputBarView/InputBarView.swift b/nMessenger/Source/Messenger/Components/InputBarView/InputBarView.swift index accf981..1719c44 100644 --- a/nMessenger/Source/Messenger/Components/InputBarView/InputBarView.swift +++ b/nMessenger/Source/Messenger/Components/InputBarView/InputBarView.swift @@ -15,19 +15,19 @@ import UIKit InputBarView class for NMessenger. Define the input bar for NMessenger. This is where the user would type text and open the camera or photo library. */ -public class InputBarView: UIView, InputBarViewProtocol { +open class InputBarView: UIView, InputBarViewProtocol { //MARK: IBOutlets //@IBOutlets for input area view - @IBOutlet public weak var textInputAreaView: UIView! + @IBOutlet open weak var textInputAreaView: UIView! //@IBOutlets for input view - @IBOutlet public weak var textInputView: UITextView! + @IBOutlet open weak var textInputView: UITextView! //MARK: Public Parameters //MARK: Private Parameters //NMessengerViewController where to input is sent to - public var controller:NMessengerViewController! + open var controller:NMessengerViewController! // MARK: Initialisers /** @@ -37,11 +37,11 @@ public class InputBarView: UIView, InputBarViewProtocol { */ public required init() { - super.init(frame: CGRectMake(0, 0, 0, 0)) + super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0)) } public required init(controller:NMessengerViewController) { - super.init(frame: CGRectZero) + super.init(frame: CGRect.zero) self.controller = controller } /** diff --git a/nMessenger/Source/Messenger/Components/InputBarView/NMessengerBarView.swift b/nMessenger/Source/Messenger/Components/InputBarView/NMessengerBarView.swift index 87d73e7..9d0952e 100755 --- a/nMessenger/Source/Messenger/Components/InputBarView/NMessengerBarView.swift +++ b/nMessenger/Source/Messenger/Components/InputBarView/NMessengerBarView.swift @@ -17,25 +17,25 @@ import Photos InputBarView class for NMessenger. Define the input bar for NMessenger. This is where the user would type text and open the camera or photo library. */ -public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelegate { +open class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelegate { //MARK: IBOutlets //@IBOutlet for InputBarView - @IBOutlet public var InputBarView: UIView! + @IBOutlet open var InputBarView: UIView! //@IBOutlet for send button - @IBOutlet public weak var sendButton: UIButton! + @IBOutlet open weak var sendButton: UIButton! //@IBOutlets NSLayoutConstraint input area view height - @IBOutlet public weak var textInputAreaViewHeight: NSLayoutConstraint! + @IBOutlet open weak var textInputAreaViewHeight: NSLayoutConstraint! //@IBOutlets NSLayoutConstraint input view height - @IBOutlet public weak var textInputViewHeight: NSLayoutConstraint! + @IBOutlet open weak var textInputViewHeight: NSLayoutConstraint! //MARK: Public Parameters //Rerrence to CameraViewController - public lazy var cameraVC: CameraViewController = CameraViewController() + open lazy var cameraVC: CameraViewController = CameraViewController() //CGFloat to the fine the number of rows a user can type - public var numberOfRows:CGFloat = 3 + open var numberOfRows:CGFloat = 3 //String as placeholder text in input view - public var inputTextViewPlaceholder: String = "NMessenger" + open var inputTextViewPlaceholder: String = "NMessenger" { willSet(newVal) { @@ -45,7 +45,7 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega //MARK: Private Parameters //CGFloat as defualt height for input view - private let textInputViewHeightConst:CGFloat = 30 + fileprivate let textInputViewHeightConst:CGFloat = 30 // MARK: Initialisers /** @@ -87,12 +87,12 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega /** Loads the view from nib file InputBarView and does intial setup. */ - private func loadFromBundle() { - NSBundle(forClass: NMessengerViewController.self).loadNibNamed("NMessengerBarView", owner: self, options: nil)[0] as! UIView + fileprivate func loadFromBundle() { + _ = Bundle(for: NMessengerViewController.self).loadNibNamed("NMessengerBarView", owner: self, options: nil)?[0] as! UIView self.addSubview(InputBarView) InputBarView.frame = self.bounds textInputView.delegate = self - self.sendButton.enabled = false + self.sendButton.isEnabled = false cameraVC.cameraDelegate = self } @@ -102,13 +102,13 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega /** Implementing textViewShouldBeginEditing in order to set the text indictor at position 0 */ - public func textViewShouldBeginEditing(textView: UITextView) -> Bool { + open func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { textView.text = "" textView.textColor = UIColor.n1DarkestGreyColor() - UIView.animateWithDuration(0.1) { - self.sendButton.enabled = true - } - dispatch_async(dispatch_get_main_queue(), { + UIView.animate(withDuration: 0.1, animations: { + self.sendButton.isEnabled = true + }) + DispatchQueue.main.async(execute: { textView.selectedRange = NSMakeRange(0, 0) }); return true @@ -116,13 +116,13 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega /** Implementing textViewShouldEndEditing in order to re-add placeholder and hiding send button when lost focus */ - public func textViewShouldEndEditing(textView: UITextView) -> Bool { + open func textViewShouldEndEditing(_ textView: UITextView) -> Bool { if self.textInputView.text.isEmpty { self.addInputSelectorPlaceholder() } - UIView.animateWithDuration(0.1) { - self.sendButton.enabled = false - } + UIView.animate(withDuration: 0.1, animations: { + self.sendButton.isEnabled = false + }) self.textInputView.resignFirstResponder() return true } @@ -131,19 +131,19 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega Re-sizing the text area to default values when the return button is tapped Limit the amount of rows a user can write to the value of numberOfRows */ - public func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { + open func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if textView.text == "" && (text != "\n") { - UIView.animateWithDuration(0.1) { - self.sendButton.enabled = true - } + UIView.animate(withDuration: 0.1, animations: { + self.sendButton.isEnabled = true + }) return true } else if (text == "\n") && textView.text != ""{ if textView == self.textInputView { textInputViewHeight.constant = textInputViewHeightConst textInputAreaViewHeight.constant = textInputViewHeightConst+10 - self.controller.sendText(self.textInputView.text,isIncomingMessage: false) + _ = self.controller.sendText(self.textInputView.text,isIncomingMessage: false) self.textInputView.text = "" return false } @@ -151,15 +151,15 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega else if (text != "\n") { - let newText = (textView.text as NSString).stringByReplacingCharactersInRange(range, withString: text) + let newText = (textView.text as NSString).replacingCharacters(in: range, with: text) - var textWidth: CGFloat = CGRectGetWidth(UIEdgeInsetsInsetRect(textView.frame, textView.textContainerInset)) + var textWidth: CGFloat = UIEdgeInsetsInsetRect(textView.frame, textView.textContainerInset).width textWidth -= 2.0 * textView.textContainer.lineFragmentPadding - let boundingRect: CGRect = newText.boundingRectWithSize(CGSizeMake(textWidth, 0), options: [NSStringDrawingOptions.UsesLineFragmentOrigin,NSStringDrawingOptions.UsesFontLeading], attributes: [NSFontAttributeName: textView.font!], context: nil) + let boundingRect: CGRect = newText.boundingRect(with: CGSize(width: textWidth, height: 0), options: [NSStringDrawingOptions.usesLineFragmentOrigin,NSStringDrawingOptions.usesFontLeading], attributes: [NSFontAttributeName: textView.font!], context: nil) - let numberOfLines = CGRectGetHeight(boundingRect) / textView.font!.lineHeight; + let numberOfLines = boundingRect.height / textView.font!.lineHeight; return numberOfLines <= numberOfRows @@ -169,10 +169,10 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega /** Implementing textViewDidChange in order to resize the text input area */ - public func textViewDidChange(textView: UITextView) { + open func textViewDidChange(_ textView: UITextView) { let fixedWidth = textView.frame.size.width - textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max)) - let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max)) + textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude)) + let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude)) var newFrame = textView.frame newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height) @@ -188,9 +188,9 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega /** Adds placeholder text and change the color of textInputView */ - private func addInputSelectorPlaceholder() { + fileprivate func addInputSelectorPlaceholder() { self.textInputView.text = self.inputTextViewPlaceholder - self.textInputView.textColor = UIColor.lightGrayColor() + self.textInputView.textColor = UIColor.lightGray } //MARK: @IBAction selectors @@ -198,12 +198,12 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega Send button selector Sends the text in textInputView to the controller */ - @IBAction public func sendButtonClicked(sender: AnyObject) { + @IBAction open func sendButtonClicked(_ sender: AnyObject) { textInputViewHeight.constant = textInputViewHeightConst textInputAreaViewHeight.constant = textInputViewHeightConst+10 if self.textInputView.text != "" { - self.controller.sendText(self.textInputView.text,isIncomingMessage: false) + _ = self.controller.sendText(self.textInputView.text,isIncomingMessage: false) self.textInputView.text = "" } } @@ -212,26 +212,26 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega Requests camera and photo library permission if needed Open camera and/or photo library to take/select a photo */ - @IBAction public func plusClicked(sender: AnyObject?) { + @IBAction open func plusClicked(_ sender: AnyObject?) { let authStatus = cameraVC.cameraAuthStatus let photoLibAuthStatus = cameraVC.photoLibAuthStatus - if(authStatus != AVAuthorizationStatus.Authorized) { + if(authStatus != AVAuthorizationStatus.authorized) { cameraVC.isCameraPermissionGranted({(granted) in if(granted) { - self.cameraVC.cameraAuthStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) - dispatch_async(dispatch_get_main_queue(), { () -> Void in - self.controller.presentViewController(self.cameraVC, animated: true, completion: nil) + self.cameraVC.cameraAuthStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) + DispatchQueue.main.async(execute: { () -> Void in + self.controller.present(self.cameraVC, animated: true, completion: nil) }) } else { - self.cameraVC.cameraAuthStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) - if(photoLibAuthStatus != PHAuthorizationStatus.Authorized) { + self.cameraVC.cameraAuthStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) + if(photoLibAuthStatus != PHAuthorizationStatus.authorized) { self.cameraVC.requestPhotoLibraryPermissions({ (granted) in if(granted) { self.cameraVC.photoLibAuthStatus = PHPhotoLibrary.authorizationStatus() - dispatch_async(dispatch_get_main_queue(), { () -> Void in - self.controller.presentViewController(self.cameraVC, animated: true, completion: + DispatchQueue.main.async(execute: { () -> Void in + self.controller.present(self.cameraVC, animated: true, completion: { ModalAlertUtilities.postGoToSettingToEnableCameraModal(fromController: self.cameraVC) }) @@ -247,16 +247,16 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega } else { - dispatch_async(dispatch_get_main_queue(), { () -> Void in - self.controller.presentViewController(self.cameraVC, animated: true, completion: nil) + DispatchQueue.main.async(execute: { () -> Void in + self.controller.present(self.cameraVC, animated: true, completion: nil) }) } } }) } else {//also check if photo gallery permissions are granted - self.cameraVC.cameraAuthStatus = AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) - dispatch_async(dispatch_get_main_queue(), { () -> Void in - self.controller.presentViewController(self.cameraVC, animated: true, completion: nil) + self.cameraVC.cameraAuthStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) + DispatchQueue.main.async(execute: { () -> Void in + self.controller.present(self.cameraVC, animated: true, completion: nil) }) } } @@ -267,17 +267,17 @@ public class NMessengerBarView: InputBarView,UITextViewDelegate,CameraViewDelega Implemetning CameraView delegate method Close the CameraView and sends the image to the controller */ - public func pickedImage(image: UIImage!) { - self.cameraVC.dismissViewControllerAnimated(true, completion: nil) + open func pickedImage(_ image: UIImage!) { + self.cameraVC.dismiss(animated: true, completion: nil) - self.controller.sendImage(image,isIncomingMessage: false) + _ = self.controller.sendImage(image,isIncomingMessage: false) } /** Implemetning CameraView delegate method Close the CameraView */ - public func cameraCancelSelection() { - cameraVC.dismissViewControllerAnimated(true, completion: nil) + open func cameraCancelSelection() { + cameraVC.dismiss(animated: true, completion: nil) } } diff --git a/nMessenger/Source/Messenger/Components/NMessenger.swift b/nMessenger/Source/Messenger/Components/NMessenger.swift index 07fe999..d671cc3 100755 --- a/nMessenger/Source/Messenger/Components/NMessenger.swift +++ b/nMessenger/Source/Messenger/Components/NMessenger.swift @@ -16,26 +16,26 @@ import AsyncDisplayKit Triggered when a load batch content should be called. This method is called on a background thread. Make sure to add prefetched content with *endBatchFetchWithMessages(messages: [GeneralMessengerCell])* */ - optional func batchFetchContent() + @objc optional func batchFetchContent() /** Returns a newly created loading Indicator that should be used at the top of the messenger */ - optional func batchFetchLoadingIndicator()->GeneralMessengerCell + @objc optional func batchFetchLoadingIndicator()->GeneralMessengerCell } //MARK: NMessengerSemaphore /** N Messenger Framework. Works in a multithreaded environment + implements prefetching at the head */ -public class NMessenger: UIView { +open class NMessenger: UIView { //MARK: Messenger enum - private enum NMessengerSection: Int { - case Messenger = 0 - case TypingIndicator = 1 + fileprivate enum NMessengerSection: Int { + case messenger = 0 + case typingIndicator = 1 } //MARK: Messenger state - private struct NMessengerState { + fileprivate struct NMessengerState { //Messenger states var itemCount: Int var lastContentOffset: CGFloat @@ -47,21 +47,21 @@ public class NMessenger: UIView { var typingIndicators: [GeneralMessengerCell] //Locks - let messageLock: dispatch_semaphore_t + let messageLock: DispatchSemaphore let batchFetchLock: ASBatchContext //initializer - static let initialState = NMessengerState(itemCount: 0, lastContentOffset: 0, scrollDirection: .None, cellBufferStartIndex: Int.max, cellBuffer: [GeneralMessengerCell](), typingIndicators: [GeneralMessengerCell](),messageLock: dispatch_semaphore_create(1), batchFetchLock: ASBatchContext()) + static let initialState = NMessengerState(itemCount: 0, lastContentOffset: 0, scrollDirection: ASScrollDirection(), cellBufferStartIndex: Int.max, cellBuffer: [GeneralMessengerCell](), typingIndicators: [GeneralMessengerCell](),messageLock: DispatchSemaphore(value: 1), batchFetchLock: ASBatchContext()) } //MARK: Private variables /** ASTableView for messages*/ - public var messengerNode = ASTableNode() + open var messengerNode:ASTableNode = ASTableNode() /** Holds a state for the amount of content and if the messenger is fetching or not */ - private var state: NMessengerState = .initialState + fileprivate var state: NMessengerState = .initialState /** Used internally to prevent unwrapping for every usage*/ - private var messengerDelegate: NMessengerDelegate { + fileprivate var messengerDelegate: NMessengerDelegate { get { if let delegate = delegate { return delegate @@ -71,7 +71,7 @@ public class NMessenger: UIView { } } /** Gets a generic loading indicator */ - private var standardLoadingIndicator: GeneralMessengerCell { + fileprivate var standardLoadingIndicator: GeneralMessengerCell { get { return HeadLoadingIndicator() } @@ -80,14 +80,14 @@ public class NMessenger: UIView { //MARK: Public variables /**Delegate*/ - public var delegate: NMessengerDelegate? + open var delegate: NMessengerDelegate? /**Triggers the delegate batch fetch function when NMessenger determines a batch fetch is needed. Defaults to true. **Note** *batchFetchContent()* must also be implemented */ - public var doesBatchFetch: Bool = false + open var doesBatchFetch: Bool = false //MARK: Initializers public init() { - super.init(frame: CGRectZero) + super.init(frame: CGRect.zero) setupView() } @@ -102,17 +102,17 @@ public class NMessenger: UIView { } /** Creates the messenger tableview and sets defaults*/ - private func setupView() { + fileprivate func setupView() { - self.messengerNode.view.keyboardDismissMode = .OnDrag - self.addSubview(messengerNode.view) + self.messengerNode.view.keyboardDismissMode = .onDrag + self.addSubview((messengerNode.view)!) messengerNode.delegate = self messengerNode.dataSource = self - messengerNode.view.setTuningParameters(ASRangeTuningParameters(leadingBufferScreenfuls: 2, trailingBufferScreenfuls: 1), forRangeType: .Display) + messengerNode.view.setTuningParameters(ASRangeTuningParameters(leadingBufferScreenfuls: 2, trailingBufferScreenfuls: 1), for: .display) - messengerNode.view.separatorStyle = UITableViewCellSeparatorStyle.None + messengerNode.view.separatorStyle = UITableViewCellSeparatorStyle.none messengerNode.view.allowsSelection = false messengerNode.view.showsVerticalScrollIndicator = false messengerNode.view.automaticallyAdjustsContentOffset = true @@ -121,11 +121,11 @@ public class NMessenger: UIView { //MARK: Public functions /** Override layoutSubviews to update messenger table frame*/ - override public func layoutSubviews() { + override open func layoutSubviews() { super.layoutSubviews() //update frame messengerNode.frame = self.bounds - messengerNode.view.separatorStyle = UITableViewCellSeparatorStyle.None + messengerNode.view.separatorStyle = UITableViewCellSeparatorStyle.none } //MARK: Adding messages @@ -135,8 +135,8 @@ public class NMessenger: UIView { - parameter scrollsToMessage: If marked true, the tableview will scroll to the newly added message */ - public func addMessage(message: GeneralMessengerCell, scrollsToMessage: Bool) { - self.addMessages([message], scrollsToMessage: scrollsToMessage, withAnimation: .None) + open func addMessage(_ message: GeneralMessengerCell, scrollsToMessage: Bool) { + self.addMessages([message], scrollsToMessage: scrollsToMessage, withAnimation: .none) } /** @@ -146,7 +146,7 @@ public class NMessenger: UIView { message - parameter animation: An animation for newly added cell */ - public func addMessage(message: GeneralMessengerCell, scrollsToMessage: Bool, withAnimation animation: UITableViewRowAnimation) { + open func addMessage(_ message: GeneralMessengerCell, scrollsToMessage: Bool, withAnimation animation: UITableViewRowAnimation) { self.addMessages([message], scrollsToMessage: scrollsToMessage, withAnimation: animation) } @@ -156,9 +156,9 @@ public class NMessenger: UIView { - parameter scrollsToMessage: If marked true, the tableview will scroll to the newly added message */ - public func addMessages(messages: [GeneralMessengerCell], scrollsToMessage: Bool) { + open func addMessages(_ messages: [GeneralMessengerCell], scrollsToMessage: Bool) { self.waitForMessageLock { - self.addMessages(messages, atIndex: self.state.itemCount, scrollsToMessage: scrollsToMessage, animation: .None, completion: nil) + self.addMessages(messages, atIndex: self.state.itemCount, scrollsToMessage: scrollsToMessage, animation: .none, completion: nil) } } @@ -169,7 +169,7 @@ public class NMessenger: UIView { - parameter animation: An animation for newly added cell message */ - public func addMessages(messages: [GeneralMessengerCell], scrollsToMessage: Bool, withAnimation animation: UITableViewRowAnimation) { + open func addMessages(_ messages: [GeneralMessengerCell], scrollsToMessage: Bool, withAnimation animation: UITableViewRowAnimation) { self.waitForMessageLock { self.addMessages(messages, atIndex: self.state.itemCount, scrollsToMessage: scrollsToMessage, animation: animation, completion: nil) } @@ -183,7 +183,7 @@ public class NMessenger: UIView { message - parameter completion: A completion handler */ - public func addMessagesWithBlock(messages: [GeneralMessengerCell], scrollsToMessage: Bool, withAnimation animation: UITableViewRowAnimation, completion: (()->Void)?) { + open func addMessagesWithBlock(_ messages: [GeneralMessengerCell], scrollsToMessage: Bool, withAnimation animation: UITableViewRowAnimation, completion: (()->Void)?) { self.waitForMessageLock { self.addMessages(messages, atIndex: self.state.itemCount, scrollsToMessage: scrollsToMessage, animation: animation, completion: completion) } @@ -195,12 +195,12 @@ public class NMessenger: UIView { - parameter messages: messages to add to the head of the tableview */ - public func endBatchFetchWithMessages(messages: [GeneralMessengerCell]) { + open func endBatchFetchWithMessages(_ messages: [GeneralMessengerCell]) { //make sure we are in the process of a batch fetch if self.state.batchFetchLock.isFetching() { self.waitForMessageLock { - self.removeCells(atIndexes: [NSIndexPath(forRow: 0, inSection: NMessengerSection.Messenger.rawValue)], animation: .None, completion: { - self.addMessages(messages, atIndex: 0, scrollsToMessage: false, animation: .None, completion: { + self.removeCells(atIndexes: [IndexPath(row: 0, section: NMessengerSection.messenger.rawValue)], animation: .none, completion: { + self.addMessages(messages, atIndex: 0, scrollsToMessage: false, animation: .none, completion: { self.state.batchFetchLock.completeBatchFetching(true) }) }) @@ -212,14 +212,14 @@ public class NMessenger: UIView { /** Clears all messages in the messenger. (Fire and forget) */ - public func clearALLMessages() { + open func clearALLMessages() { self.waitForMessageLock { - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { let oldState = self.state self.state.itemCount = 0 - self.renderDiff(oldState, startIndex: 0, animation: .None, completion: { + self.renderDiff(oldState, startIndex: 0, animation: .none, completion: { //must decrement the semaphore - dispatch_semaphore_signal(self.state.messageLock) + self.state.messageLock.signal() }) } } @@ -231,7 +231,7 @@ public class NMessenger: UIView { - parameter message: the message that should be deleted - parameter animation: a row animation for deleting the cell */ - public func removeMessage(message: GeneralMessengerCell, animation: UITableViewRowAnimation) { + open func removeMessage(_ message: GeneralMessengerCell, animation: UITableViewRowAnimation) { self.removeMessages([message], animation: animation) } @@ -241,7 +241,7 @@ public class NMessenger: UIView { - parameter messages: the messages that should be deleted - parameter animation: a row animation for deleting the cell */ - public func removeMessages(messages: [GeneralMessengerCell], animation: UITableViewRowAnimation) { + open func removeMessages(_ messages: [GeneralMessengerCell], animation: UITableViewRowAnimation) { self.removeMessagesWithBlock(messages, animation: animation, completion: nil) } @@ -251,12 +251,12 @@ public class NMessenger: UIView { - parameter messages: the messages that should be deleted - parameter animation: a row animation for deleting the cell */ - public func removeMessagesWithBlock(messages: [GeneralMessengerCell], animation: UITableViewRowAnimation, completion: (()->Void)?) { + open func removeMessagesWithBlock(_ messages: [GeneralMessengerCell], animation: UITableViewRowAnimation, completion: (()->Void)?) { self.waitForMessageLock { - dispatch_async(dispatch_get_main_queue()) { - var indexPaths = [NSIndexPath]() + DispatchQueue.main.async { + var indexPaths = [IndexPath]() for message in messages { - if let indexPath = self.messengerNode.view.indexPathForNode(message) { + if let indexPath = self.messengerNode.view.indexPath(for: message) { indexPaths.append(indexPath) } //remove current table node @@ -264,7 +264,7 @@ public class NMessenger: UIView { } self.removeCells(atIndexes: indexPaths, animation: animation, completion: { //unlock the semaphore - dispatch_semaphore_signal(self.state.messageLock) + self.state.messageLock.signal() completion?() }) } @@ -276,14 +276,14 @@ public class NMessenger: UIView { Scrolls to the last message in the messenger. (Fire and forget) - parameter animated: The move is animated or not */ - public func scrollToLastMessage(animated: Bool) { + open func scrollToLastMessage(_ animated: Bool) { waitForMessageLock { - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { if let indexPath = self.pickLastIndexPath() { - self.scrollToIndex(indexPath.row, inSection: indexPath.section, atPosition: .Bottom, animated: animated) + self.scrollToIndex((indexPath as NSIndexPath).row, inSection: (indexPath as NSIndexPath).section, atPosition: .bottom, animated: animated) } //unlock the semaphore - dispatch_semaphore_signal(self.state.messageLock) + self.state.messageLock.signal() } } } @@ -294,14 +294,14 @@ public class NMessenger: UIView { - parameter atPosition: The location to scroll to - parameter animated: The move is animated or not */ - public func scrollToMessage(message: GeneralMessengerCell, atPosition position: UITableViewScrollPosition, animated: Bool) { + open func scrollToMessage(_ message: GeneralMessengerCell, atPosition position: UITableViewScrollPosition, animated: Bool) { waitForMessageLock { - dispatch_async(dispatch_get_main_queue()) { - if let indexPath = self.messengerNode.view.indexPathForNode(message) { - self.scrollToIndex(indexPath.row, inSection: indexPath.section, atPosition: position, animated: animated) + DispatchQueue.main.async { + if let indexPath = self.messengerNode.view.indexPath(for: message) { + self.scrollToIndex((indexPath as NSIndexPath).row, inSection: (indexPath as NSIndexPath).section, atPosition: position, animated: animated) } //unlock the semaphore - dispatch_semaphore_signal(self.state.messageLock) + self.state.messageLock.signal() } } } @@ -313,23 +313,23 @@ public class NMessenger: UIView { - parameter scrollsToLast: should the messenger scroll to the bottom - parameter animated: If the scroll is animated */ - public func addTypingIndicator(indicator: GeneralMessengerCell, scrollsToLast: Bool, animated: Bool, completion: (()->Void)?) { + open func addTypingIndicator(_ indicator: GeneralMessengerCell, scrollsToLast: Bool, animated: Bool, completion: (()->Void)?) { waitForMessageLock { - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { self.state.typingIndicators.append(indicator) - let set = NSIndexSet(index: NMessengerSection.TypingIndicator.rawValue) + let set = IndexSet(integer: NMessengerSection.typingIndicator.rawValue) CATransaction.begin() CATransaction.setCompletionBlock(completion) self.messengerNode.view.beginUpdates() - self.messengerNode.view.reloadSections(set, withRowAnimation: .Left) - self.messengerNode.view.endUpdatesAnimated(true, completion: { (completed: Bool) -> Void in + self.messengerNode.view.reloadSections(set, with: .left) + self.messengerNode.view.endUpdates(animated: true, completion: { (completed: Bool) -> Void in if scrollsToLast { if let indexPath = self.pickLastIndexPath() { - self.scrollToIndex(indexPath.row, inSection: indexPath.section, atPosition: .Bottom, animated: true) + self.scrollToIndex((indexPath as NSIndexPath).row, inSection: (indexPath as NSIndexPath).section, atPosition: .bottom, animated: true) } } //unlock the semaphore - dispatch_semaphore_signal(self.state.messageLock) + self.state.messageLock.signal() }) CATransaction.commit() } @@ -342,7 +342,7 @@ public class NMessenger: UIView { - parameter scrollsToLast: should the messenger scroll to the bottom - parameter animated: If the scroll is animated */ - public func removeTypingIndicator(indicator: GeneralMessengerCell, scrollsToLast: Bool, animated: Bool) { + open func removeTypingIndicator(_ indicator: GeneralMessengerCell, scrollsToLast: Bool, animated: Bool) { self.removeTypingIndicator(indicator, scrollsToLast: scrollsToLast, animated: animated, completion: nil) } @@ -352,26 +352,26 @@ public class NMessenger: UIView { - parameter scrollsToLast: should the messenger scroll to the bottom - parameter animated: If the scroll is animated */ - public func removeTypingIndicator(indicator: GeneralMessengerCell, scrollsToLast: Bool, animated: Bool, completion: (()->Void)?) { + open func removeTypingIndicator(_ indicator: GeneralMessengerCell, scrollsToLast: Bool, animated: Bool, completion: (()->Void)?) { waitForMessageLock { - dispatch_async(dispatch_get_main_queue()) { - if let index = self.state.typingIndicators.indexOf(indicator){ + DispatchQueue.main.async { + if let index = self.state.typingIndicators.index(of: indicator){ - self.state.typingIndicators.removeAtIndex(index) + self.state.typingIndicators.remove(at: index) - let set = NSIndexSet(index: NMessengerSection.TypingIndicator.rawValue) + let set = IndexSet(integer: NMessengerSection.typingIndicator.rawValue) CATransaction.begin() CATransaction.setCompletionBlock(completion) self.messengerNode.view.beginUpdates() - self.messengerNode.view.reloadSections(set, withRowAnimation: .Fade) - self.messengerNode.view.endUpdatesAnimated(true, completion: { (completed: Bool) -> Void in + self.messengerNode.view.reloadSections(set, with: .fade) + self.messengerNode.view.endUpdates(animated: true, completion: { (completed: Bool) -> Void in if scrollsToLast { if let indexPath = self.pickLastIndexPath() { - self.scrollToIndex(indexPath.row, inSection: indexPath.section, atPosition: .Bottom, animated: true) + self.scrollToIndex((indexPath as NSIndexPath).row, inSection: (indexPath as NSIndexPath).section, atPosition: .bottom, animated: true) } } //unlock the semaphore - dispatch_semaphore_signal(self.state.messageLock) + self.state.messageLock.signal() }) CATransaction.commit() } @@ -382,7 +382,7 @@ public class NMessenger: UIView { /** - returns: true if the messenger contains the loading indicator */ - public func hasIndicator(indicator: GeneralMessengerCell) -> Bool { + open func hasIndicator(_ indicator: GeneralMessengerCell) -> Bool { return self.state.typingIndicators.contains(indicator) } @@ -393,8 +393,8 @@ public class NMessenger: UIView { - parameter message: A GeneralMessengerCell that could or could not exist in the messenger - returns: A Bool indicating whether or not the cell exists in the messenger */ - public func hasMessage(message: GeneralMessengerCell) -> Bool { - let hasNode = (self.messengerNode.view.indexPathForNode(message) != nil) + open func hasMessage(_ message: GeneralMessengerCell) -> Bool { + let hasNode = (self.messengerNode.view.indexPath(for: message) != nil) return hasNode } @@ -403,11 +403,11 @@ public class NMessenger: UIView { - returns: An array containing all of the messages in the messager. These are in order as they appear. */ - public func allMessages() -> [GeneralMessengerCell] { + open func allMessages() -> [GeneralMessengerCell] { var retArray = [GeneralMessengerCell]() for index in 0..Void) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { - dispatch_semaphore_wait(self.state.messageLock, DISPATCH_TIME_FOREVER) + fileprivate func waitForMessageLock(_ completion: @escaping ()->Void) { + //DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default).async { + + DispatchQueue.global().async { + _ = self.state.messageLock.wait(timeout: DispatchTime.distantFuture) completion() } } @@ -438,8 +440,8 @@ public class NMessenger: UIView { - parameter scrollsToMessage: If marked true, the tableview will scroll to the newly added message */ - private func addMessages(messages: [GeneralMessengerCell], atIndex index: Int, scrollsToMessage: Bool, animation: UITableViewRowAnimation, completion: (()->Void)?) { - dispatch_async(dispatch_get_main_queue()) { + fileprivate func addMessages(_ messages: [GeneralMessengerCell], atIndex index: Int, scrollsToMessage: Bool, animation: UITableViewRowAnimation, completion: (()->Void)?) { + DispatchQueue.main.async { if messages.count > 0 { //set the new state let oldState = self.state @@ -453,24 +455,24 @@ public class NMessenger: UIView { } //render new cells self.renderDiff(oldState, startIndex: self.state.cellBufferStartIndex, animation: animation, completion: { - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { //reset start index self.state.cellBufferStartIndex = Int.max self.state.cellBuffer = [GeneralMessengerCell]() //scroll to the message if scrollsToMessage { if let indexPath = self.pickLastIndexPath() { - self.scrollToIndex(indexPath.row, inSection: indexPath.section, atPosition: .Bottom, animated: true) + self.scrollToIndex((indexPath as NSIndexPath).row, inSection: (indexPath as NSIndexPath).section, atPosition: .bottom, animated: true) } } //unlock the semaphore - dispatch_semaphore_signal(self.state.messageLock) + self.state.messageLock.signal() completion?() } }) } else { //unlock the semaphore - dispatch_semaphore_signal(self.state.messageLock) + self.state.messageLock.signal() completion?() } } @@ -480,15 +482,15 @@ public class NMessenger: UIView { Picks the last index path in the messenger. Used when there are typing indicators in the messenger - returns: An NSIndexPath representing the last element */ - private func pickLastIndexPath()-> NSIndexPath? { + fileprivate func pickLastIndexPath()-> IndexPath? { if self.state.typingIndicators.isEmpty { //if there are no tying indicators let lastMessage = self.state.itemCount-1 if lastMessage >= 0 { - return NSIndexPath(forItem: lastMessage, inSection: NMessengerSection.Messenger.rawValue) + return IndexPath(item: lastMessage, section: NMessengerSection.messenger.rawValue) } } else { - return NSIndexPath(forItem: self.state.typingIndicators.count - 1, inSection: NMessengerSection.TypingIndicator.rawValue) + return IndexPath(item: self.state.typingIndicators.count - 1, section: NMessengerSection.typingIndicator.rawValue) } return nil } @@ -500,9 +502,9 @@ public class NMessenger: UIView { - parameter position: a position to scroll to - parameter animated: bool indicating if the scroll should be animated */ - private func scrollToIndex(index: Int, inSection section: Int, atPosition position: UITableViewScrollPosition, animated: Bool) { - let indexPath = (NSIndexPath(forRow: index, inSection: section)) - self.messengerNode.view.scrollToRowAtIndexPath(indexPath, atScrollPosition: position, animated: animated) + fileprivate func scrollToIndex(_ index: Int, inSection section: Int, atPosition position: UITableViewScrollPosition, animated: Bool) { + let indexPath = (IndexPath(row: index, section: section)) + self.messengerNode.view.scrollToRow(at: indexPath, at: position, animated: animated) } /** @@ -510,7 +512,7 @@ public class NMessenger: UIView { Offest is from the top of the messengerNode ASTableView - parameter offset: the offset from the top of the scrollview */ - private func shouldHandleBatchFetch(offset: CGPoint) { + fileprivate func shouldHandleBatchFetch(_ offset: CGPoint) { if doesBatchFetch && self.messengerDelegate.batchFetchContent != nil { if shouldBatchFetch(self.state.batchFetchLock, direction: self.state.scrollDirection, bounds: messengerNode.view.bounds, contentSize: messengerNode.view.contentSize, targetOffset: offset, leadingScreens: messengerNode.view.leadingScreensForBatching) { @@ -524,20 +526,25 @@ public class NMessenger: UIView { /** Triggers a batch fetch on a background thread. */ - private func batchFetchDataInBackground() { + fileprivate func batchFetchDataInBackground() { waitForMessageLock { //add a loading spinner to the top if let loadingIndicator = self.messengerDelegate.batchFetchLoadingIndicator?() { //if delegate method - self.addMessages([loadingIndicator], atIndex: 0, scrollsToMessage: false, animation: .None, completion: nil) + self.addMessages([loadingIndicator], atIndex: 0, scrollsToMessage: false, animation: .none, completion: nil) } else { //standard nmessenger indicator - self.addMessages([self.standardLoadingIndicator], atIndex: 0, scrollsToMessage: false, animation: .None, completion: nil) + self.addMessages([self.standardLoadingIndicator], atIndex: 0, scrollsToMessage: false, animation: .none, completion: nil) } } //run this on a background thread - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { + DispatchQueue.global().async { self.messengerDelegate.batchFetchContent?() } + + + //DispatchQueue.global(priority: DispatchQueue.GlobalQueuePriority.default).async { + // self.messengerDelegate.batchFetchContent?() + //} } /** @@ -548,19 +555,19 @@ public class NMessenger: UIView { - parameter animation: an animation to remove the cells - parameter completion: closure to signify the end of the remove event */ - private func removeCells(atIndexes indexes: [NSIndexPath], animation: UITableViewRowAnimation, completion: (()->Void)?) { - dispatch_async(dispatch_get_main_queue()) { + fileprivate func removeCells(atIndexes indexes: [IndexPath], animation: UITableViewRowAnimation, completion: (()->Void)?) { + DispatchQueue.main.async { //update the state self.state.itemCount -= indexes.count //remove rows let tableView = self.messengerNode.view - tableView.beginUpdates() - tableView.deleteRowsAtIndexPaths(indexes, withRowAnimation: animation) + tableView?.beginUpdates() + tableView?.deleteRows(at: indexes, with: animation) //done animating - let animated = animation != .None - tableView.endUpdatesAnimated(animated) { (success) in + let animated = animation != .none + tableView?.endUpdates(animated: animated) { (success) in completion?() } } @@ -573,27 +580,27 @@ public class NMessenger: UIView { - parameter startIndex: Where to insert or delete the cells - parameter completion: Closure which notifies that the table is done adding cells */ - private func renderDiff(oldState: NMessengerState, startIndex: Int, animation: UITableViewRowAnimation, completion: (()->Void)?) { + fileprivate func renderDiff(_ oldState: NMessengerState, startIndex: Int, animation: UITableViewRowAnimation, completion: (()->Void)?) { let tableView = messengerNode.view - tableView.beginUpdates() + tableView?.beginUpdates() // Add or remove items let rowCountChange = state.itemCount - oldState.itemCount if rowCountChange > 0 { let indexPaths = (startIndex.. Bool { + fileprivate func shouldBatchFetch(_ context: ASBatchContext, direction: ASScrollDirection, bounds: CGRect, contentSize: CGSize, targetOffset: CGPoint, leadingScreens: CGFloat) -> Bool { if context.isFetching() { return false } - if direction != .Up { + if direction != .up { return false } - if leadingScreens <= 0 || CGRectEqualToRect(bounds, CGRectZero) { + if leadingScreens <= 0 || bounds.equalTo(CGRect.zero) { return false } @@ -639,7 +646,7 @@ extension NMessenger { - parameter scrollsToLastMessage: A that indicates whether the tableview should scroll to the last message in the group - paramter toPosition: the position to scroll to */ - public func addMessageToMessageGroup(message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToLastMessage: Bool) { + public func addMessageToMessageGroup(_ message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToLastMessage: Bool) { self.addMessageToMessageGroup(message, messageGroup: messageGroup, scrollsToLastMessage: scrollsToLastMessage, completion: nil) } @@ -651,7 +658,7 @@ extension NMessenger { - paramter toPosition: the position to scroll to - parameter completion: a block to be called after the content has been added */ - public func addMessageToMessageGroup(message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToLastMessage: Bool, completion: (()->Void)?) { + public func addMessageToMessageGroup(_ message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToLastMessage: Bool, completion: (()->Void)?) { messageGroup.addMessageToGroup(message, completion: { if scrollsToLastMessage { self.scrollToLastMessage(true) @@ -668,13 +675,13 @@ extension NMessenger { - paramter toPosition: the position to scroll to - parameter completion: a block to be called after the content has been added */ - public func addMessageToMessageGroup(message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToMessage: Bool, toPosition position: UITableViewScrollPosition?, completion: (()->Void)?) { + public func addMessageToMessageGroup(_ message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToMessage: Bool, toPosition position: UITableViewScrollPosition?, completion: (()->Void)?) { messageGroup.addMessageToGroup(message, completion: { if scrollsToMessage { if let position = position { self.scrollToMessage(messageGroup, atPosition: position, animated: true) } else { - self.scrollToMessage(messageGroup, atPosition: .Bottom, animated: true) + self.scrollToMessage(messageGroup, atPosition: .bottom, animated: true) } } @@ -689,7 +696,7 @@ extension NMessenger { - parameter scrollsToLastMessage: A that indicates whether the tableview should scroll to the last message in the group - paramter toPosition: the position to scroll to */ - public func removeMessageFromMessageGroup(message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToLastMessage: Bool, toPosition position: UITableViewScrollPosition?) { + public func removeMessageFromMessageGroup(_ message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToLastMessage: Bool, toPosition position: UITableViewScrollPosition?) { self.removeMessageFromMessageGroup(message, messageGroup: messageGroup, scrollsToLastMessage: scrollsToLastMessage, toPosition: position, completion: nil) } @@ -701,12 +708,12 @@ extension NMessenger { - paramter toPosition: the position to scroll to - parameter completion: a block to be called after the content has been removed */ - public func removeMessageFromMessageGroup(message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToLastMessage: Bool, toPosition position: UITableViewScrollPosition?, completion: (()->Void)?) { + public func removeMessageFromMessageGroup(_ message: GeneralMessengerCell, messageGroup: MessageGroup, scrollsToLastMessage: Bool, toPosition position: UITableViewScrollPosition?, completion: (()->Void)?) { //If it is the last message, remove it if self.hasMessage(messageGroup) { if messageGroup.messages.count == 1 && messageGroup.messages.first == message { - let animation = messageGroup.isIncomingMessage ? UITableViewRowAnimation.Left : UITableViewRowAnimation.Right + let animation = messageGroup.isIncomingMessage ? UITableViewRowAnimation.left : UITableViewRowAnimation.right self.removeMessagesWithBlock([messageGroup], animation: animation, completion: { completion?() }) @@ -720,7 +727,7 @@ extension NMessenger { if let position = position { self.scrollToMessage(messageGroup, atPosition: position, animated: true) } else { - self.scrollToMessage(messageGroup, atPosition: .Bottom, animated: true) + self.scrollToMessage(messageGroup, atPosition: .bottom, animated: true) } } completion?() @@ -732,12 +739,12 @@ extension NMessenger { extension NMessenger: ASTableViewDelegate, ASTableViewDataSource { //MARK: footer - public func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { return UIView() } - public func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - if section == NMessengerSection.Messenger.rawValue { + public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + if section == NMessengerSection.messenger.rawValue { return 5 } @@ -745,12 +752,12 @@ extension NMessenger: ASTableViewDelegate, ASTableViewDataSource { } //MARK: header - public func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { return UIView() } - public func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - if section == NMessengerSection.Messenger.rawValue { + public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + if section == NMessengerSection.messenger.rawValue { return 5 } @@ -758,30 +765,30 @@ extension NMessenger: ASTableViewDelegate, ASTableViewDataSource { } //MARK: ASTableNode - public func shouldBatchFetchForTableView(tableView: ASTableView) -> Bool { + public func shouldBatchFetch(for tableView: ASTableView) -> Bool { return false } - public func tableView(tableView: ASTableView, nodeForRowAtIndexPath indexPath: NSIndexPath) -> ASCellNode { + public func tableView(_ tableView: ASTableView, nodeForRowAt indexPath: IndexPath) -> ASCellNode { - switch indexPath.section { - case NMessengerSection.Messenger.rawValue: - if indexPath.row >= self.state.cellBufferStartIndex { - return self.state.cellBuffer[indexPath.row - self.state.cellBufferStartIndex] + switch (indexPath as NSIndexPath).section { + case NMessengerSection.messenger.rawValue: + if (indexPath as NSIndexPath).row >= self.state.cellBufferStartIndex { + return self.state.cellBuffer[(indexPath as NSIndexPath).row - self.state.cellBufferStartIndex] } - return tableView.nodeForRowAtIndexPath(indexPath) - case NMessengerSection.TypingIndicator.rawValue: - return self.state.typingIndicators[indexPath.row] + return tableView.nodeForRow(at: indexPath) + case NMessengerSection.typingIndicator.rawValue: + return self.state.typingIndicators[(indexPath as NSIndexPath).row] default: //should never come here return ASCellNode() } } - public func numberOfSectionsInTableView(tableView: UITableView) -> Int { + public func numberOfSections(in tableView: UITableView) -> Int { return 2 } - public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 0 { return self.state.itemCount } else { @@ -794,27 +801,34 @@ extension NMessenger: ASTableViewDelegate, ASTableViewDataSource { /** When this is triggered, we decide if a prefetch is needed */ - public func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { + + public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { + //if targetContentOffset != nil { + shouldHandleBatchFetch((targetContentOffset.pointee)) + //} + } + + /*public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer?) { if targetContentOffset != nil { - shouldHandleBatchFetch(targetContentOffset.memory) + shouldHandleBatchFetch((targetContentOffset?.pointee)!) } - } + }*/ /** Keeps track of the current scroll direction. This state can be obtained by accessing the scrollDirection property */ - public func scrollViewDidScroll(scrollView: UIScrollView) { + public func scrollViewDidScroll(_ scrollView: UIScrollView) { //is scrolling down if self.state.lastContentOffset < scrollView.contentOffset.y { - self.state.scrollDirection = .Down + self.state.scrollDirection = .down } //is scrolling up else if self.state.lastContentOffset > scrollView.contentOffset.y { - self.state.scrollDirection = .Up + self.state.scrollDirection = .up } //set to compare against next scroll action self.state.lastContentOffset = scrollView.contentOffset.y; } -} \ No newline at end of file +} diff --git a/nMessenger/Source/Messenger/NMessengerViewController.swift b/nMessenger/Source/Messenger/NMessengerViewController.swift index c5b5648..29ac93b 100755 --- a/nMessenger/Source/Messenger/NMessengerViewController.swift +++ b/nMessenger/Source/Messenger/NMessengerViewController.swift @@ -14,27 +14,47 @@ import UIKit import AVFoundation import Photos import AsyncDisplayKit +fileprivate func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l < r + case (nil, _?): + return true + default: + return false + } +} -public class NMessengerViewController: UIViewController, UITextViewDelegate, NMessengerDelegate, UIGestureRecognizerDelegate { +fileprivate func >= (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (l?, r?): + return l >= r + default: + return !(lhs < rhs) + } +} + + +open class NMessengerViewController: UIViewController, UITextViewDelegate, NMessengerDelegate, UIGestureRecognizerDelegate { //MARK: Views //This is messenger view - public var messengerView: NMessenger! + open var messengerView: NMessenger! //This is input view - public var inputBarView: InputBarView! + open var inputBarView: InputBarView! //MARK: Private Variables //Bool to indicate if the keyboard is open - public private(set) var isKeyboardIsShown : Bool = false + open fileprivate(set) var isKeyboardIsShown : Bool = false //NSLayoutConstraint for the input bar spacing from the bottom - private var inputBarBottomSpacing:NSLayoutConstraint = NSLayoutConstraint() + fileprivate var inputBarBottomSpacing:NSLayoutConstraint = NSLayoutConstraint() //NSLayoutConstraint for the messenger spacing from the input bar - private var messengerBottomSpacing:NSLayoutConstraint = NSLayoutConstraint() + fileprivate var messengerBottomSpacing:NSLayoutConstraint = NSLayoutConstraint() //MARK: Public Variables //UIEdgeInsets for padding for each message - public var messagePadding: UIEdgeInsets = UIEdgeInsets(top: 5, left: 0, bottom: 5, right: 0) + open var messagePadding: UIEdgeInsets = UIEdgeInsets(top: 5, left: 0, bottom: 5, right: 0) /** A shared bubble configuration to use for new messages. Defaults to **SharedBubbleConfiguration***/ - public var sharedBubbleConfiguration: BubbleConfigurationProtocol = StandardBubbleConfiguration() + open var sharedBubbleConfiguration: BubbleConfigurationProtocol = StandardBubbleConfiguration() // MARK: Initialisers @@ -54,7 +74,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter nibBundleOrNil: Can be NSBundle Adds observers */ - public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) { + public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) self.addObservers() } @@ -79,14 +99,14 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Adds observer for UIKeyboardWillChangeFrameNotification */ - private func addObservers() { - NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(NMessengerViewController.keyboardNotification(_:)), name: UIKeyboardWillChangeFrameNotification, object: nil) + fileprivate func addObservers() { + NotificationCenter.default.addObserver(self, selector: #selector(NMessengerViewController.keyboardNotification(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil) } /** Removes observer for UIKeyboardWillChangeFrameNotification */ - private func removeObservers() { - NSNotificationCenter.defaultCenter().removeObserver(self) + fileprivate func removeObservers() { + NotificationCenter.default.removeObserver(self) } // MARK: Controller LifeCycle @@ -94,7 +114,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe Overriding viewDidLoad to setup the view controller Calls helper methods */ - override public func viewDidLoad() { + override open func viewDidLoad() { super.viewDidLoad() //load views loadMessengerView() @@ -102,11 +122,11 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe setUpConstraintsForViews() //swipe down let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(NMessengerViewController.respondToSwipeGesture(_:))) - swipeDown.direction = UISwipeGestureRecognizerDirection.Down + swipeDown.direction = UISwipeGestureRecognizerDirection.down self.inputBarView.textInputAreaView.addGestureRecognizer(swipeDown) } - override public func viewDidAppear(animated: Bool) { + override open func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) } @@ -114,15 +134,15 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Creates NMessenger view and adds it to the view */ - private func loadMessengerView() { - self.messengerView = NMessenger(frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 63)) + fileprivate func loadMessengerView() { + self.messengerView = NMessenger(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height - 63)) messengerView.delegate = self self.view.addSubview(self.messengerView) } /** Adds BaseInputBarView to the view */ - private func loadInputView() + fileprivate func loadInputView() { self.inputBarView = self.getInputBar() self.view.addSubview(inputBarView) @@ -132,33 +152,33 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe Override this method to create your own custom InputBarView - Returns: A view that extends InputBarView */ - public func getInputBar() -> InputBarView + open func getInputBar() -> InputBarView { return NMessengerBarView(controller: self) } /** Adds auto layout constraints for NMessenger and InputBarView */ - private func setUpConstraintsForViews() + fileprivate func setUpConstraintsForViews() { inputBarView.translatesAutoresizingMaskIntoConstraints = false - self.inputBarBottomSpacing = NSLayoutConstraint(item: self.inputBarView, attribute: .Bottom, relatedBy: .Equal, toItem: self.bottomLayoutGuide, attribute: .Top, multiplier: 1, constant: 0) + self.inputBarBottomSpacing = NSLayoutConstraint(item: self.inputBarView, attribute: .bottom, relatedBy: .equal, toItem: self.bottomLayoutGuide, attribute: .top, multiplier: 1, constant: 0) self.view.addConstraint(self.inputBarBottomSpacing) - self.view.addConstraint(NSLayoutConstraint(item: self.inputBarView, attribute: .Leading, relatedBy: .Equal, toItem: self.view, attribute: .Leading, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: self.inputBarView, attribute: .Trailing, relatedBy: .Equal, toItem: self.view, attribute: .Trailing, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: inputBarView, attribute: .Height, relatedBy: .GreaterThanOrEqual, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: self.inputBarView.frame.size.height)) + self.view.addConstraint(NSLayoutConstraint(item: self.inputBarView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 0)) + self.view.addConstraint(NSLayoutConstraint(item: self.inputBarView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: 0)) + self.view.addConstraint(NSLayoutConstraint(item: inputBarView, attribute: .height, relatedBy: .greaterThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: self.inputBarView.frame.size.height)) self.messengerView.translatesAutoresizingMaskIntoConstraints = false - self.messengerBottomSpacing = NSLayoutConstraint(item: self.messengerView, attribute: .Bottom, relatedBy: .Equal, toItem: self.inputBarView, attribute: .Top, multiplier: 1, constant: 0) + self.messengerBottomSpacing = NSLayoutConstraint(item: self.messengerView, attribute: .bottom, relatedBy: .equal, toItem: self.inputBarView, attribute: .top, multiplier: 1, constant: 0) self.view.addConstraint(self.messengerBottomSpacing) - self.view.addConstraint(NSLayoutConstraint(item: self.messengerView, attribute: .Top, relatedBy: .Equal, toItem: self.topLayoutGuide, attribute: .Bottom, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: self.messengerView, attribute: .Leading, relatedBy: .Equal, toItem: self.view, attribute: .Leading, multiplier: 1, constant: 0)) - self.view.addConstraint(NSLayoutConstraint(item: self.messengerView, attribute: .Trailing, relatedBy: .Equal, toItem: self.view, attribute: .Trailing, multiplier: 1, constant: 0)) + self.view.addConstraint(NSLayoutConstraint(item: self.messengerView, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0)) + self.view.addConstraint(NSLayoutConstraint(item: self.messengerView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1, constant: 0)) + self.view.addConstraint(NSLayoutConstraint(item: self.messengerView, attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailing, multiplier: 1, constant: 0)) } - override public func shouldAutorotate() -> Bool { - if (UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft || - UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight || - UIDevice.currentDevice().orientation == UIDeviceOrientation.Unknown) { + override open var shouldAutorotate : Bool { + if (UIDevice.current.orientation == UIDeviceOrientation.landscapeLeft || + UIDevice.current.orientation == UIDeviceOrientation.landscapeRight || + UIDevice.current.orientation == UIDeviceOrientation.unknown) { return false; } else { @@ -170,14 +190,14 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Moves InputBarView up and down accoridng to the location of the keyboard */ - func keyboardNotification(notification: NSNotification) { - if let userInfo = notification.userInfo { - let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() - let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 + func keyboardNotification(_ notification: Notification) { + if let userInfo = (notification as NSNotification).userInfo { + let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue + let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber - let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue + let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions().rawValue let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw) - if endFrame?.origin.y >= UIScreen.mainScreen().bounds.size.height { + if endFrame?.origin.y >= UIScreen.main.bounds.size.height { self.inputBarBottomSpacing.constant = 0 self.isKeyboardIsShown = false } else { @@ -192,8 +212,8 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe } self.isKeyboardIsShown = true } - UIView.animateWithDuration(duration, - delay: NSTimeInterval(0), + UIView.animate(withDuration: duration, + delay: TimeInterval(0), options: animationCurve, animations: { self.view.layoutIfNeeded() if self.isKeyboardIsShown { @@ -209,7 +229,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Closes the messenger on swipe on InputBarView */ - func respondToSwipeGesture(gesture: UIGestureRecognizer) { + func respondToSwipeGesture(_ gesture: UIGestureRecognizer) { self.inputBarView.textInputView.resignFirstResponder() } @@ -217,19 +237,19 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Called when adding a text to the messenger. Override this function to add your message to the VC */ - public func sendText(text: String, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func sendText(_ text: String, isIncomingMessage:Bool) -> GeneralMessengerCell { return self.postText(text,isIncomingMessage: isIncomingMessage) } /** Called when adding an image to the messenger. Override this function to add your message to the VC */ - public func sendImage(image: UIImage, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func sendImage(_ image: UIImage, isIncomingMessage:Bool) -> GeneralMessengerCell { return self.postImage(image,isIncomingMessage: isIncomingMessage) } /** Called when adding a network image to the messenger. Override this function to add your message to the VC */ - public func sendNetworkImage(imageURL: String, isIncomingMessage:Bool) -> GeneralMessengerCell + open func sendNetworkImage(_ imageURL: String, isIncomingMessage:Bool) -> GeneralMessengerCell { return self.postNetworkImage(imageURL,isIncomingMessage: isIncomingMessage) } @@ -237,7 +257,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Called when adding a collection view with views to the messenger. Override this function to add your message to the VC */ - public func sendCollectionViewWithViews(views: [UIView], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell + open func sendCollectionViewWithViews(_ views: [UIView], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { return self.postCollectionView(views, numberOfRows: numberOfRows, isIncomingMessage: isIncomingMessage) } @@ -245,7 +265,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Called when adding a collection view with nodes to the messenger. Override this function to add your message to the VC */ - public func sendCollectionViewWithNodes(nodes: [ASDisplayNode], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell + open func sendCollectionViewWithNodes(_ nodes: [ASDisplayNode], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { return self.postCollectionView(nodes, numberOfRows: numberOfRows, isIncomingMessage: isIncomingMessage) } @@ -254,7 +274,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Called when adding a a custom view to the messenger. Override this function to add your message to the VC */ - public func sendCustomView(view: UIView, isIncomingMessage:Bool) -> GeneralMessengerCell + open func sendCustomView(_ view: UIView, isIncomingMessage:Bool) -> GeneralMessengerCell { return self.postCustomContent(view, isIncomingMessage: isIncomingMessage) } @@ -262,7 +282,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** Called when adding a a custom node to the messenger. Override this function to add your message to the VC */ - public func sendCustomNode(node: ASDisplayNode, isIncomingMessage:Bool) -> GeneralMessengerCell + open func sendCustomNode(_ node: ASDisplayNode, isIncomingMessage:Bool) -> GeneralMessengerCell { return self.postCustomContent(node, isIncomingMessage: isIncomingMessage) } @@ -273,13 +293,13 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe Adds a message to the messenger - parameter message: GeneralMessageCell */ - public func addMessageToMessenger(message:GeneralMessengerCell) + open func addMessageToMessenger(_ message:GeneralMessengerCell) { message.currentViewController = self if message.isIncomingMessage == false { - self.messengerView.addMessage(message, scrollsToMessage: true, withAnimation: .Right) + self.messengerView.addMessage(message, scrollsToMessage: true, withAnimation: .right) } else { - self.messengerView.addMessage(message, scrollsToMessage: true, withAnimation: .Left) + self.messengerView.addMessage(message, scrollsToMessage: true, withAnimation: .left) } } @@ -287,16 +307,16 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe Adds a general message to the messenger. Default animation is fade. - parameter messageGroup: MessageGroup */ - public func addGeneralMessengerToMessenger(message: GeneralMessengerCell) { + open func addGeneralMessengerToMessenger(_ message: GeneralMessengerCell) { message.currentViewController = self - self.messengerView.addMessage(message, scrollsToMessage: false, withAnimation: .Fade) + self.messengerView.addMessage(message, scrollsToMessage: false, withAnimation: .fade) } /** Creates an incoming typing indicator - parameter avatar: an avatar to add to the typing indicator message */ - public func createTypingIndicator(avatar: ASDisplayNode?) -> GeneralMessengerCell + open func createTypingIndicator(_ avatar: ASDisplayNode?) -> GeneralMessengerCell { let typing = TypingIndicatorContent(bubbleConfiguration: self.sharedBubbleConfiguration) let newMessage = MessageNode(content: typing) @@ -309,7 +329,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe Adds an incoming typing indicator to the messenger - parameter avatar: an avatar to add to the typing indicator message */ - public func showTypingIndicator(avatar: ASDisplayNode?) -> GeneralMessengerCell + open func showTypingIndicator(_ avatar: ASDisplayNode?) -> GeneralMessengerCell { let newMessage = self.createTypingIndicator(avatar) messengerView.addTypingIndicator(newMessage, scrollsToLast: false, animated: true, completion: nil) @@ -319,7 +339,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe /** removes a typing indicator from the messenger */ - public func removeTypingIndicator(indicator: GeneralMessengerCell) { + open func removeTypingIndicator(_ indicator: GeneralMessengerCell) { messengerView.removeTypingIndicator(indicator, scrollsToLast: false, animated: true) } @@ -331,7 +351,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - public func createTextMessage(text: String, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func createTextMessage(_ text: String, isIncomingMessage:Bool) -> GeneralMessengerCell { let textContent = TextContentNode(textMessageString: text, currentViewController: self, bubbleConfiguration: self.sharedBubbleConfiguration) let newMessage = MessageNode(content: textContent) newMessage.cellPadding = messagePadding @@ -347,7 +367,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - private func postText(text: String, isIncomingMessage:Bool) -> GeneralMessengerCell { + fileprivate func postText(_ text: String, isIncomingMessage:Bool) -> GeneralMessengerCell { let newMessage = createTextMessage(text, isIncomingMessage: isIncomingMessage) self.addMessageToMessenger(newMessage) return newMessage @@ -359,7 +379,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - public func createImageMessage(image: UIImage, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func createImageMessage(_ image: UIImage, isIncomingMessage:Bool) -> GeneralMessengerCell { let imageContent = ImageContentNode(image: image, bubbleConfiguration: self.sharedBubbleConfiguration) let newMessage = MessageNode(content: imageContent) newMessage.cellPadding = messagePadding @@ -375,7 +395,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - private func postImage(image: UIImage, isIncomingMessage:Bool) -> GeneralMessengerCell { + fileprivate func postImage(_ image: UIImage, isIncomingMessage:Bool) -> GeneralMessengerCell { let newMessage = self.createImageMessage(image, isIncomingMessage: isIncomingMessage) self.addMessageToMessenger(newMessage) return newMessage @@ -388,7 +408,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - public func createNetworkImageMessage(url: String, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func createNetworkImageMessage(_ url: String, isIncomingMessage:Bool) -> GeneralMessengerCell { let networkImageContent = NetworkImageContentNode(imageURL: url, bubbleConfiguration: self.sharedBubbleConfiguration) let newMessage = MessageNode(content: networkImageContent) newMessage.cellPadding = messagePadding @@ -404,7 +424,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - private func postNetworkImage(url: String, isIncomingMessage:Bool) -> GeneralMessengerCell { + fileprivate func postNetworkImage(_ url: String, isIncomingMessage:Bool) -> GeneralMessengerCell { let newMessage = self.createNetworkImageMessage(url, isIncomingMessage: isIncomingMessage) self.addMessageToMessenger(newMessage) return newMessage @@ -417,7 +437,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - public func createCollectionViewMessage(views: [UIView], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func createCollectionViewMessage(_ views: [UIView], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { let collectionViewContent = CollectionViewContentNode(withCustomViews: views, andNumberOfRows: numberOfRows, bubbleConfiguration: self.sharedBubbleConfiguration) let newMessage = MessageNode(content: collectionViewContent) newMessage.cellPadding = messagePadding @@ -434,7 +454,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - private func postCollectionView(views: [UIView], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { + fileprivate func postCollectionView(_ views: [UIView], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { let newMessage = self.createCollectionViewMessage(views, numberOfRows: numberOfRows, isIncomingMessage: isIncomingMessage) self.addMessageToMessenger(newMessage) return newMessage @@ -447,7 +467,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - public func createCollectionNodeMessage(nodes: [ASDisplayNode], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func createCollectionNodeMessage(_ nodes: [ASDisplayNode], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { let collectionViewContent = CollectionViewContentNode(withCustomNodes: nodes, andNumberOfRows: numberOfRows, bubbleConfiguration: self.sharedBubbleConfiguration) let newMessage = MessageNode(content: collectionViewContent) newMessage.cellPadding = messagePadding @@ -464,7 +484,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - private func postCollectionView(nodes: [ASDisplayNode], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { + fileprivate func postCollectionView(_ nodes: [ASDisplayNode], numberOfRows:CGFloat, isIncomingMessage:Bool) -> GeneralMessengerCell { let newMessage = self.createCollectionNodeMessage(nodes, numberOfRows: numberOfRows, isIncomingMessage: isIncomingMessage) self.addMessageToMessenger(newMessage) return newMessage @@ -476,7 +496,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - public func createCustomContentViewMessage(view: UIView, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func createCustomContentViewMessage(_ view: UIView, isIncomingMessage:Bool) -> GeneralMessengerCell { let customView = CustomContentNode(withCustomView: view, bubbleConfiguration: self.sharedBubbleConfiguration) let newMessage = MessageNode(content: customView) newMessage.cellPadding = messagePadding @@ -492,7 +512,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - private func postCustomContent(view: UIView, isIncomingMessage:Bool) -> GeneralMessengerCell { + fileprivate func postCustomContent(_ view: UIView, isIncomingMessage:Bool) -> GeneralMessengerCell { let newMessage = self.createCustomContentViewMessage(view, isIncomingMessage: isIncomingMessage) self.addMessageToMessenger(newMessage) return newMessage @@ -505,7 +525,7 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - public func createCustomContentNodeMessage(node: ASDisplayNode, isIncomingMessage:Bool) -> GeneralMessengerCell { + open func createCustomContentNodeMessage(_ node: ASDisplayNode, isIncomingMessage:Bool) -> GeneralMessengerCell { let customView = CustomContentNode(withCustomNode: node, bubbleConfiguration: self.sharedBubbleConfiguration) let newMessage = MessageNode(content: customView) newMessage.cellPadding = messagePadding @@ -521,10 +541,10 @@ public class NMessengerViewController: UIViewController, UITextViewDelegate, NMe - parameter isIncomingMessage: if message is incoming or outgoing - returns: the newly created message */ - private func postCustomContent(node: ASDisplayNode, isIncomingMessage:Bool) -> GeneralMessengerCell { + fileprivate func postCustomContent(_ node: ASDisplayNode, isIncomingMessage:Bool) -> GeneralMessengerCell { let newMessage = self.createCustomContentNodeMessage(node, isIncomingMessage: isIncomingMessage) self.addMessageToMessenger(newMessage) return newMessage } -} \ No newline at end of file +} diff --git a/nMessenger/Source/Utilities/ModalAlertUtilities.swift b/nMessenger/Source/Utilities/ModalAlertUtilities.swift index f452066..75fea44 100755 --- a/nMessenger/Source/Utilities/ModalAlertUtilities.swift +++ b/nMessenger/Source/Utilities/ModalAlertUtilities.swift @@ -15,19 +15,19 @@ import UIKit /** Custom alerts for NMessenger */ -public class ModalAlertUtilities { +open class ModalAlertUtilities { /** Genreal error alert message - parameter controller: Must be UIViewController. Where to present to alert. */ class func postGenericErrorModal(fromController controller: UIViewController) { - let alert = UIAlertController(title: "Error", message: "An error occurred. Please try again later", preferredStyle: .Alert) - let cancelAction = UIAlertAction(title: "Okay", style: .Cancel) { (action) in - alert.dismissViewControllerAnimated(true, completion: nil) + let alert = UIAlertController(title: "Error", message: "An error occurred. Please try again later", preferredStyle: .alert) + let cancelAction = UIAlertAction(title: "Okay", style: .cancel) { (action) in + alert.dismiss(animated: true, completion: nil) } alert.addAction(cancelAction) - dispatch_async(dispatch_get_main_queue(), { () -> Void in - controller.presentViewController(alert, animated: true, completion: nil) + DispatchQueue.main.async(execute: { () -> Void in + controller.present(alert, animated: true, completion: nil) }) } /** @@ -37,20 +37,20 @@ public class ModalAlertUtilities { */ class func postGoToSettingToEnableCameraAndLibraryModal(fromController controller: UIViewController) { - let alert = UIAlertController(title: "", message: "Allow access to your camera & photo library to start uploading photos with N1", preferredStyle: .Alert) - let cancelAction = UIAlertAction(title: "Cancel", style: .Destructive) { (action) in - alert.dismissViewControllerAnimated(true, completion: nil) + let alert = UIAlertController(title: "", message: "Allow access to your camera & photo library to start uploading photos with N1", preferredStyle: .alert) + let cancelAction = UIAlertAction(title: "Cancel", style: .destructive) { (action) in + alert.dismiss(animated: true, completion: nil) } - let settingsAction = UIAlertAction(title: "Go to Settings", style: .Default) { (alertAction) in - if let appSettings = NSURL(string: UIApplicationOpenSettingsURLString) { - UIApplication.sharedApplication().openURL(appSettings) + let settingsAction = UIAlertAction(title: "Go to Settings", style: .default) { (alertAction) in + if let appSettings = URL(string: UIApplicationOpenSettingsURLString) { + UIApplication.shared.openURL(appSettings) } } alert.addAction(settingsAction) alert.addAction(cancelAction) - dispatch_async(dispatch_get_main_queue(), { () -> Void in - controller.presentViewController(alert, animated: true, completion: nil) + DispatchQueue.main.async(execute: { () -> Void in + controller.present(alert, animated: true, completion: nil) }) } /** @@ -60,20 +60,20 @@ public class ModalAlertUtilities { */ class func postGoToSettingToEnableCameraModal(fromController controller: UIViewController) { - let alert = UIAlertController(title: "", message: "Allow access to your camera to start taking photos and uploading photos from your library with N1", preferredStyle: .Alert) - let cancelAction = UIAlertAction(title: "Cancel", style: .Destructive) { (action) in - alert.dismissViewControllerAnimated(true, completion: nil) + let alert = UIAlertController(title: "", message: "Allow access to your camera to start taking photos and uploading photos from your library with N1", preferredStyle: .alert) + let cancelAction = UIAlertAction(title: "Cancel", style: .destructive) { (action) in + alert.dismiss(animated: true, completion: nil) } - let settingsAction = UIAlertAction(title: "Go to Settings", style: .Default) { (alertAction) in - if let appSettings = NSURL(string: UIApplicationOpenSettingsURLString) { - UIApplication.sharedApplication().openURL(appSettings) + let settingsAction = UIAlertAction(title: "Go to Settings", style: .default) { (alertAction) in + if let appSettings = URL(string: UIApplicationOpenSettingsURLString) { + UIApplication.shared.openURL(appSettings) } } alert.addAction(settingsAction) alert.addAction(cancelAction) - dispatch_async(dispatch_get_main_queue(), { () -> Void in - controller.presentViewController(alert, animated: true, completion: nil) + DispatchQueue.main.async(execute: { () -> Void in + controller.present(alert, animated: true, completion: nil) }) } /** @@ -83,20 +83,20 @@ public class ModalAlertUtilities { */ class func postGoToSettingToEnableLibraryModal(fromController controller: UIViewController) { - let alert = UIAlertController(title: "", message: "Allow access to your photo library to start uploading photos from you library with N1", preferredStyle: .Alert) - let cancelAction = UIAlertAction(title: "Cancel", style: .Destructive) { (action) in - alert.dismissViewControllerAnimated(true, completion: nil) + let alert = UIAlertController(title: "", message: "Allow access to your photo library to start uploading photos from you library with N1", preferredStyle: .alert) + let cancelAction = UIAlertAction(title: "Cancel", style: .destructive) { (action) in + alert.dismiss(animated: true, completion: nil) } - let settingsAction = UIAlertAction(title: "Go to Settings", style: .Default) { (alertAction) in - if let appSettings = NSURL(string: UIApplicationOpenSettingsURLString) { - UIApplication.sharedApplication().openURL(appSettings) + let settingsAction = UIAlertAction(title: "Go to Settings", style: .default) { (alertAction) in + if let appSettings = URL(string: UIApplicationOpenSettingsURLString) { + UIApplication.shared.openURL(appSettings) } } alert.addAction(settingsAction) alert.addAction(cancelAction) - dispatch_async(dispatch_get_main_queue(), { () -> Void in - controller.presentViewController(alert, animated: true, completion: nil) + DispatchQueue.main.async(execute: { () -> Void in + controller.present(alert, animated: true, completion: nil) }) } -} \ No newline at end of file +} diff --git a/nMessenger/Source/Utilities/UIColor+N1Colors.swift b/nMessenger/Source/Utilities/UIColor+N1Colors.swift index 199283e..6a09ac2 100755 --- a/nMessenger/Source/Utilities/UIColor+N1Colors.swift +++ b/nMessenger/Source/Utilities/UIColor+N1Colors.swift @@ -68,7 +68,7 @@ extension UIColor { return UIColor(white: 0.0, alpha: 0.5) } - class func colorFromRGB(rgbHexValue: UInt) -> UIColor { + class func colorFromRGB(_ rgbHexValue: UInt) -> UIColor { return UIColor( red: CGFloat((rgbHexValue & 0xFF0000) >> 16) / 255.0, green: CGFloat((rgbHexValue & 0x00FF00) >> 8) / 255.0, @@ -84,4 +84,4 @@ extension UIColor { return UIColor(red: red, green: green, blue: blue, alpha: 1.0) } - } \ No newline at end of file + } diff --git a/nMessenger/Source/Utilities/UIFont+N1Fonts.swift b/nMessenger/Source/Utilities/UIFont+N1Fonts.swift index ee67e1d..52d1081 100755 --- a/nMessenger/Source/Utilities/UIFont+N1Fonts.swift +++ b/nMessenger/Source/Utilities/UIFont+N1Fonts.swift @@ -17,50 +17,50 @@ import UIKit */ extension UIFont { class func n1H1Font() -> UIFont { - return UIFont.systemFontOfSize(28.0, weight: UIFontWeightThin) + return UIFont.systemFont(ofSize: 28.0, weight: UIFontWeightThin) } class func n1H2Font() -> UIFont { - return UIFont.systemFontOfSize(20.0, weight: UIFontWeightLight) + return UIFont.systemFont(ofSize: 20.0, weight: UIFontWeightLight) } class func n1H3Font() -> UIFont { - return UIFont.systemFontOfSize(18.0, weight: UIFontWeightRegular) + return UIFont.systemFont(ofSize: 18.0, weight: UIFontWeightRegular) } class func n1LinkFont() -> UIFont { - return UIFont.systemFontOfSize(16.0, weight: UIFontWeightSemibold) + return UIFont.systemFont(ofSize: 16.0, weight: UIFontWeightSemibold) } class func n1TextStyleFont() -> UIFont { - return UIFont.systemFontOfSize(16.0, weight: UIFontWeightRegular) + return UIFont.systemFont(ofSize: 16.0, weight: UIFontWeightRegular) } class func n1B1Font() -> UIFont { - return UIFont.systemFontOfSize(16.0, weight: UIFontWeightRegular) + return UIFont.systemFont(ofSize: 16.0, weight: UIFontWeightRegular) } class func n1TextStyle3Font() -> UIFont { - return UIFont.systemFontOfSize(12.0, weight: UIFontWeightBold) + return UIFont.systemFont(ofSize: 12.0, weight: UIFontWeightBold) } class func n1TextStyle3MiniFont() -> UIFont { - return UIFont.systemFontOfSize(8.0, weight: UIFontWeightBold) + return UIFont.systemFont(ofSize: 8.0, weight: UIFontWeightBold) } class func n1TextStyle2Font() -> UIFont { - return UIFont.systemFontOfSize(14.0, weight: UIFontWeightRegular) + return UIFont.systemFont(ofSize: 14.0, weight: UIFontWeightRegular) } class func n1B2Font() -> UIFont { - return UIFont.systemFontOfSize(14.0, weight: UIFontWeightRegular) + return UIFont.systemFont(ofSize: 14.0, weight: UIFontWeightRegular) } class func n1TextStyle4Font() -> UIFont { - return UIFont.systemFontOfSize(14.0, weight: UIFontWeightLight) + return UIFont.systemFont(ofSize: 14.0, weight: UIFontWeightLight) } class func n1CaptionFont() -> UIFont { - return UIFont.systemFontOfSize(12.0, weight: UIFontWeightMedium) + return UIFont.systemFont(ofSize: 12.0, weight: UIFontWeightMedium) } -} \ No newline at end of file +} diff --git a/nMessengerTests/Messenger/NMessengerTests.swift b/nMessengerTests/Messenger/NMessengerTests.swift index 993a03b..7b0b9b8 100755 --- a/nMessengerTests/Messenger/NMessengerTests.swift +++ b/nMessengerTests/Messenger/NMessengerTests.swift @@ -23,19 +23,19 @@ class NMessengerTests: XCTestCase { func testInit() { let testVC = TestVC() - let messenger = NMessenger(frame: CGRectZero) + let messenger = NMessenger(frame: CGRect.zero) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) messenger.delegate = testVC XCTAssertNotNil(messenger.delegate) - XCTAssertTrue(messenger.subviews.contains(messenger.messengerNode.view)) + XCTAssertTrue(messenger.subviews.contains((messenger.messengerNode?.view)!)) let messenger2 = NMessenger() XCTAssertNotNil(messenger2) XCTAssertNotNil(messenger2.messengerNode) messenger2.delegate = testVC XCTAssertNotNil(messenger2.delegate) - XCTAssertTrue(messenger.subviews.contains(messenger.messengerNode.view)) + XCTAssertTrue(messenger.subviews.contains((messenger.messengerNode?.view)!)) } func testAdd() { @@ -46,28 +46,28 @@ class NMessengerTests: XCTestCase { messenger.addMessage(cell, scrollsToMessage: false) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) - messenger.addMessage(cell, scrollsToMessage: false, withAnimation: .None) + messenger.addMessage(cell, scrollsToMessage: false, withAnimation: .none) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) messenger.addMessages([cell], scrollsToMessage: false) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) - messenger.addMessages([cell], scrollsToMessage: false, withAnimation: .None) + messenger.addMessages([cell], scrollsToMessage: false, withAnimation: .none) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) messenger.addMessages([GeneralMessengerCell](), scrollsToMessage: true) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) - let expectationSuccess = expectationWithDescription("expectationSuccess") - messenger.addMessagesWithBlock([cell], scrollsToMessage: false, withAnimation: .None) { + let expectationSuccess = expectation(description: "expectationSuccess") + messenger.addMessagesWithBlock([cell], scrollsToMessage: false, withAnimation: .none) { XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) expectationSuccess.fulfill() } // Loop until the expectation is fulfilled - waitForExpectationsWithTimeout(5, handler: { error in + waitForExpectations(timeout: 5, handler: { error in XCTAssertNil(error, "Error") }) } @@ -135,28 +135,28 @@ class NMessengerTests: XCTestCase { XCTAssertNotNil(messenger.messengerNode) var cell = GeneralMessengerCell() - messenger.removeMessage(cell, animation: .None) + messenger.removeMessage(cell, animation: .none) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) cell = GeneralMessengerCell() messenger.addMessage(cell, scrollsToMessage: false) - messenger.removeMessage(cell, animation: .None) + messenger.removeMessage(cell, animation: .none) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) cell = GeneralMessengerCell() - messenger.removeMessages([cell], animation: .None) + messenger.removeMessages([cell], animation: .none) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) cell = GeneralMessengerCell() messenger.addMessage(cell, scrollsToMessage: false) - messenger.removeMessages([cell], animation: .None) + messenger.removeMessages([cell], animation: .none) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) - messenger.removeMessages([GeneralMessengerCell](), animation: .None) + messenger.removeMessages([GeneralMessengerCell](), animation: .none) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) @@ -166,17 +166,17 @@ class NMessengerTests: XCTestCase { XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) - let expectationSuccess = expectationWithDescription("expectationSuccess") + let expectationSuccess = expectation(description: "expectationSuccess") cell = GeneralMessengerCell() messenger.addMessage(cell, scrollsToMessage: false) - messenger.removeMessagesWithBlock([cell], animation: .None) { + messenger.removeMessagesWithBlock([cell], animation: .none) { XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) expectationSuccess.fulfill() } // Loop until the expectation is fulfilled - waitForExpectationsWithTimeout(5, handler: { error in + waitForExpectations(timeout: 5, handler: { error in XCTAssertNil(error, "Error") }) } @@ -186,36 +186,36 @@ class NMessengerTests: XCTestCase { let messenger = NMessenger() messenger.delegate = testVC - messenger.allMessages() + _ = messenger.allMessages() XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) let tmpCell = GeneralMessengerCell() messenger.addMessage(tmpCell, scrollsToMessage: false) - messenger.allMessages() + _ = messenger.allMessages() XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) - messenger.hasMessage(tmpCell) + _ = messenger.hasMessage(tmpCell) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) - messenger.hasMessage(GeneralMessengerCell()) + _ = messenger.hasMessage(GeneralMessengerCell()) XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) //do this to make sure everything else has been called - let expectationSuccess = expectationWithDescription("expectationSuccess") + let expectationSuccess = expectation(description: "expectationSuccess") let cell = GeneralMessengerCell() messenger.addMessage(cell, scrollsToMessage: false) - messenger.removeMessagesWithBlock([cell], animation: .None) { + messenger.removeMessagesWithBlock([cell], animation: .none) { XCTAssertNotNil(messenger) XCTAssertNotNil(messenger.messengerNode) expectationSuccess.fulfill() } // Loop until the expectation is fulfilled - waitForExpectationsWithTimeout(5, handler: { error in + waitForExpectations(timeout: 5, handler: { error in XCTAssertNil(error, "Error") }) } @@ -248,4 +248,4 @@ class NMessengerTests: XCTestCase { XCTAssertNotNil(messenger.messengerNode) } -} \ No newline at end of file +} diff --git a/nMessengerTests/UI Components/Chat/BubbleTests.swift b/nMessengerTests/UI Components/Chat/BubbleTests.swift index 16adfaf..7f2bf93 100755 --- a/nMessengerTests/UI Components/Chat/BubbleTests.swift +++ b/nMessengerTests/UI Components/Chat/BubbleTests.swift @@ -24,7 +24,7 @@ class BubbleTests: XCTestCase { XCTAssertEqual(rect.width, bubble.calculatedBounds.width) XCTAssertEqual(rect.height, bubble.calculatedBounds.height) - rect = CGRectZero + rect = CGRect.zero bubble.sizeToBounds(rect) XCTAssertEqual(rect.minX, bubble.calculatedBounds.minX) XCTAssertEqual(rect.minY, bubble.calculatedBounds.minY) @@ -49,7 +49,7 @@ class BubbleTests: XCTestCase { XCTAssertEqual(rect.width, bubble.calculatedBounds.width) XCTAssertEqual(rect.height, bubble.calculatedBounds.height) - rect = CGRectZero + rect = CGRect.zero bubble.sizeToBounds(rect) XCTAssertEqual(rect.minX, bubble.calculatedBounds.minX) XCTAssertEqual(rect.minY, bubble.calculatedBounds.minY) @@ -74,7 +74,7 @@ class BubbleTests: XCTestCase { XCTAssertEqual(rect.width, bubble.calculatedBounds.width) XCTAssertEqual(rect.height, bubble.calculatedBounds.height) - rect = CGRectZero + rect = CGRect.zero bubble.sizeToBounds(rect) XCTAssertEqual(rect.minX, bubble.calculatedBounds.minX) XCTAssertEqual(rect.minY, bubble.calculatedBounds.minY) @@ -99,7 +99,7 @@ class BubbleTests: XCTestCase { XCTAssertEqual(rect.width, bubble.calculatedBounds.width) XCTAssertEqual(rect.height, bubble.calculatedBounds.height) - rect = CGRectZero + rect = CGRect.zero bubble.sizeToBounds(rect) XCTAssertEqual(rect.minX, bubble.calculatedBounds.minX) XCTAssertEqual(rect.minY, bubble.calculatedBounds.minY) @@ -113,7 +113,7 @@ class BubbleTests: XCTestCase { func testBubbleImage() { let bubble = ImageBubble() - bubble.bubbleImage = UIImage(named: "MessageBubble", inBundle: NSBundle(forClass: NMessengerViewController.self), compatibleWithTraitCollection: nil) + bubble.bubbleImage = UIImage(named: "MessageBubble", in: Bundle(for: NMessengerViewController.self), compatibleWith: nil) XCTAssertNotNil(bubble.layer) XCTAssertNotNil(bubble.maskLayer) XCTAssertEqual(bubble.hasLayerMask, true) @@ -129,4 +129,4 @@ class BubbleTests: XCTestCase { XCTAssertNotNil(bubble.layer) XCTAssertNotNil(bubble.maskLayer) } -} \ No newline at end of file +} diff --git a/nMessengerTests/UI Components/Chat/CollectionViewContentNodeTests.swift b/nMessengerTests/UI Components/Chat/CollectionViewContentNodeTests.swift index 74e3335..bd69b23 100755 --- a/nMessengerTests/UI Components/Chat/CollectionViewContentNodeTests.swift +++ b/nMessengerTests/UI Components/Chat/CollectionViewContentNodeTests.swift @@ -15,12 +15,12 @@ class CollectionViewContentNodeTests: XCTestCase { func testExample() { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. - let tmpView = UIView(frame: CGRectMake(0,0,100,100)) + let tmpView = UIView(frame: CGRect(x: 0,y: 0,width: 100,height: 100)) let tempColectionNode = CollectionViewContentNode(withCustomViews: [tmpView], andNumberOfRows: 1) - let tmpSize = CGSizeMake(100, 100) - tempColectionNode.layoutSpecThatFits(ASSizeRangeMake(tmpSize, tmpSize)) - let tmpCollection = UICollectionView(frame: CGRectMake(0,0,100,100), collectionViewLayout: UICollectionViewFlowLayout()) - tempColectionNode.collectionView(tmpCollection, numberOfItemsInSection: 0) + let tmpSize = CGSize(width: 100, height: 100) + _ = tempColectionNode.layoutSpecThatFits(ASSizeRangeMake(tmpSize, tmpSize)) + let tmpCollection = UICollectionView(frame: CGRect(x: 0,y: 0,width: 100,height: 100), collectionViewLayout: UICollectionViewFlowLayout()) + _ = tempColectionNode.collectionView(tmpCollection, numberOfItemsInSection: 0) } } diff --git a/nMessengerTests/UI Components/Chat/HeadLoadingIndicatorTests.swift b/nMessengerTests/UI Components/Chat/HeadLoadingIndicatorTests.swift index 114fe11..9cf084f 100755 --- a/nMessengerTests/UI Components/Chat/HeadLoadingIndicatorTests.swift +++ b/nMessengerTests/UI Components/Chat/HeadLoadingIndicatorTests.swift @@ -17,11 +17,11 @@ class HeadLoadingIndicatorTests: XCTestCase { let loadingIndicator = HeadLoadingIndicator() XCTAssertNotNil(loadingIndicator.spinner) XCTAssertNotNil(loadingIndicator.text) - loadingIndicator.layoutSpecThatFits(ASSizeRange(min: CGSize(width: 50, height: 10), max: CGSize(width: 200, height: 20))) + _ = loadingIndicator.layoutSpecThatFits(ASSizeRange(min: CGSize(width: 50, height: 10), max: CGSize(width: 200, height: 20))) } func testSpinner() { let spinner = SpinnerNode() XCTAssertNotNil(spinner.activityIndicatorView) } -} \ No newline at end of file +} diff --git a/nMessengerTests/UI Components/Chat/NetworkImageContentNodeTests.swift b/nMessengerTests/UI Components/Chat/NetworkImageContentNodeTests.swift index 428f7da..2db40f0 100755 --- a/nMessengerTests/UI Components/Chat/NetworkImageContentNodeTests.swift +++ b/nMessengerTests/UI Components/Chat/NetworkImageContentNodeTests.swift @@ -16,12 +16,12 @@ class NetworkImageContentNodeTests: XCTestCase { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. let testNetworkImage = NetworkImageContentNode(imageURL: "http://placehold.it/100x100") - let tmpSize = CGSizeMake(100, 100) + let tmpSize = CGSize(width: 100, height: 100) let tmpRecongnizer = UITapGestureRecognizer() - testNetworkImage.layoutSpecThatFits(ASSizeRangeMake(tmpSize, tmpSize)) + _ = testNetworkImage.layoutSpecThatFits(ASSizeRangeMake(tmpSize, tmpSize)) testNetworkImage.messageNodeLongPressSelector(tmpRecongnizer) testNetworkImage.copySelector() - testNetworkImage.canBecomeFirstResponder() + _ = testNetworkImage.canBecomeFirstResponder() } } diff --git a/nMessengerTests/nMessengerTests.swift b/nMessengerTests/nMessengerTests.swift index 95553ca..a2b0035 100755 --- a/nMessengerTests/nMessengerTests.swift +++ b/nMessengerTests/nMessengerTests.swift @@ -30,7 +30,7 @@ class nMessengerTests: XCTestCase { func testPerformanceExample() { // This is an example of a performance test case. - self.measureBlock { + self.measure { // Put the code you want to measure the time of here. } }