diff --git a/TSWeChat.xcodeproj/project.pbxproj b/TSWeChat.xcodeproj/project.pbxproj index 24fbcb3..cb5f46b 100644 --- a/TSWeChat.xcodeproj/project.pbxproj +++ b/TSWeChat.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 00DD43341C8FFC9D00787685 /* bgImage_HL@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 00DD43311C8FFC9D00787685 /* bgImage_HL@2x.png */; }; + 00DD43351C8FFC9D00787685 /* cellLine@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 00DD43321C8FFC9D00787685 /* cellLine@2x.png */; }; + 00DD43361C8FFC9D00787685 /* RCActionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00DD43331C8FFC9D00787685 /* RCActionSheet.swift */; }; 521AD1D46345C1A90F878475 /* Pods_TSWeChat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0917A01A536A5EE41BF160D /* Pods_TSWeChat.framework */; }; AE3CBC551C854B90008BA4AC /* TSChatDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE3CBC541C854B90008BA4AC /* TSChatDataManager.swift */; }; AE3CBC5A1C858C3F008BA4AC /* TSChatViewController+TestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE3CBC591C858C3F008BA4AC /* TSChatViewController+TestData.swift */; }; @@ -165,6 +168,9 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 00DD43311C8FFC9D00787685 /* bgImage_HL@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "bgImage_HL@2x.png"; sourceTree = ""; }; + 00DD43321C8FFC9D00787685 /* cellLine@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "cellLine@2x.png"; sourceTree = ""; }; + 00DD43331C8FFC9D00787685 /* RCActionSheet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RCActionSheet.swift; sourceTree = ""; }; 879C4C7737B3D4DA6504869D /* Pods-TSWeChat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TSWeChat.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TSWeChat/Pods-TSWeChat.debug.xcconfig"; sourceTree = ""; }; AE3CBC541C854B90008BA4AC /* TSChatDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TSChatDataManager.swift; sourceTree = ""; }; AE3CBC591C858C3F008BA4AC /* TSChatViewController+TestData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TSChatViewController+TestData.swift"; sourceTree = ""; }; @@ -358,6 +364,16 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 00DD43301C8FFC9D00787685 /* RCActionSheet */ = { + isa = PBXGroup; + children = ( + 00DD43311C8FFC9D00787685 /* bgImage_HL@2x.png */, + 00DD43321C8FFC9D00787685 /* cellLine@2x.png */, + 00DD43331C8FFC9D00787685 /* RCActionSheet.swift */, + ); + path = RCActionSheet; + sourceTree = ""; + }; 18FCDE5FEB0C6C5536DF0CBA /* Pods */ = { isa = PBXGroup; children = ( @@ -506,6 +522,7 @@ AE92B6C01C3FF7C900968A3A /* Vendor */ = { isa = PBXGroup; children = ( + 00DD43301C8FFC9D00787685 /* RCActionSheet */, AEE69BDB1C81B61200C69224 /* VoiceConvert */, ); path = Vendor; @@ -873,6 +890,7 @@ AE8742921C7B3547003A435C /* TSContactTableViewCell.xib in Resources */, AEBEE5A91C87345700956B0C /* contact.json in Resources */, AEBEE5A81C87345700956B0C /* chat.json in Resources */, + 00DD43351C8FFC9D00787685 /* cellLine@2x.png in Resources */, AE8742881C7B079B003A435C /* TSMeAvatarTableViewCell.xib in Resources */, AEE69C051C81B61200C69224 /* libopencore-amrnb.la in Resources */, AE92B8C01C3FFC5D00968A3A /* TSMessageViewController.xib in Resources */, @@ -887,6 +905,7 @@ AEE69C0D1C81B61200C69224 /* opencore-amrnb.pc in Resources */, AEE69BAB1C81B58600C69224 /* TSChatVoiceCell.xib in Resources */, AEE69BD11C81B58600C69224 /* TSChatShareMoreView.xib in Resources */, + 00DD43341C8FFC9D00787685 /* bgImage_HL@2x.png in Resources */, AEE69C0E1C81B61200C69224 /* opencore-amrwb.pc in Resources */, AEBEE5AA1C87345700956B0C /* message.json in Resources */, AE87428A1C7B0D7D003A435C /* Kenny.jpg in Resources */, @@ -1048,6 +1067,7 @@ AE87425E1C7AE0F1003A435C /* TSUserDefaults.swift in Sources */, AEE69BBF1C81B58600C69224 /* TSChatViewController+ActionBar.swift in Sources */, AE8F49B01C46A905009C1541 /* NSDictionary+Extension.swift in Sources */, + 00DD43361C8FFC9D00787685 /* RCActionSheet.swift in Sources */, AE8742911C7B3547003A435C /* TSContactTableViewCell.swift in Sources */, AE92B8C71C3FFCE900968A3A /* TSMeViewController.swift in Sources */, AEBEE5A01C8706B800956B0C /* TSUploadModel.swift in Sources */, diff --git a/TSWeChat/Classes/Chat/ChatHelper/AudioRecordManager.swift b/TSWeChat/Classes/Chat/ChatHelper/AudioRecordManager.swift index a836735..9e9c848 100644 --- a/TSWeChat/Classes/Chat/ChatHelper/AudioRecordManager.swift +++ b/TSWeChat/Classes/Chat/ChatHelper/AudioRecordManager.swift @@ -50,7 +50,9 @@ class AudioRecordManager: NSObject { try session.setActive(true) session.requestRecordPermission{allowed in if !allowed { - TSAlertView_show("无法访问您的麦克风", message: "请到设置 -> 隐私 -> 麦克风 ,打开访问权限") + dispatch_async_safely_to_main_queue({ () -> () in + TSAlertView_show("无法访问您的麦克风", message: "请到设置 -> 隐私 -> 麦克风 ,打开访问权限") + }) } } } catch let error as NSError { diff --git a/TSWeChat/Classes/Chat/TSChatViewController+Interaction.swift b/TSWeChat/Classes/Chat/TSChatViewController+Interaction.swift index 46f421e..28cd57e 100644 --- a/TSWeChat/Classes/Chat/TSChatViewController+Interaction.swift +++ b/TSWeChat/Classes/Chat/TSChatViewController+Interaction.swift @@ -53,7 +53,11 @@ extension TSChatViewController: ChatShareMoreViewDelegate { func checkCameraPermission () { AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: {granted in if !granted { - TSAlertView_show("无法访问您的相机", message: "请到设置 -> 隐私 -> 相机 ,打开访问权限" ) + + dispatch_async_safely_to_main_queue({ () -> () in + TSAlertView_show("无法访问您的相机", message: "请到设置 -> 隐私 -> 相机 ,打开访问权限" ) + }) + } }) } @@ -266,13 +270,14 @@ extension TSChatViewController: TSChatCellDelegate { 点击了 cell 本身 */ func cellDidTaped(cell: TSChatBaseCell) { - + // TODO: goto content viewer } /** 点击了 cell 的头像 */ func cellDidTapedAvatarImage(cell: TSChatBaseCell) { + //TODO: goto user's profile TSAlertView_show("点击了头像") } @@ -280,6 +285,7 @@ extension TSChatViewController: TSChatCellDelegate { 点击了 cell 的图片 */ func cellDidTapedImageView(cell: TSChatBaseCell) { + // TODO: goto image viewer TSAlertView_show("点击了图片") } @@ -295,7 +301,12 @@ extension TSChatViewController: TSChatCellDelegate { 点击了 cell 中文字的 电话 */ func cellDidTapedPhone(cell: TSChatBaseCell, phoneString: String) { - TSAlertView_show("点击了电话") + // TOTO: show mobile operation +// TSAlertView_show("点击了电话") + + let actionSheet = RCActionSheet.actionSheet(title: "点击了电话", buttonTitles: ["复制", "打电话", "保存"], redButtonIndex: -1, delegate: nil) + actionSheet.show() + } /** diff --git a/TSWeChat/General/TSProgressHUD.swift b/TSWeChat/General/TSProgressHUD.swift index c0f6cf3..aa32c90 100644 --- a/TSWeChat/General/TSProgressHUD.swift +++ b/TSWeChat/General/TSProgressHUD.swift @@ -51,30 +51,39 @@ class TSProgressHUD: NSObject { //私有方法 private class func TSProgressHUDShow(type: HUDType, status: String? = nil, error: NSError? = nil) { + SVProgressHUD.setDefaultMaskType(.None) switch type { case .Success: - SVProgressHUD.showSuccessWithStatus(status, maskType: .None) + SVProgressHUD.showSuccessWithStatus(status) + +// SVProgressHUD.showSuccessWithStatus(status, maskType: .None) break case .ErrorObject: guard let newError = error else { - SVProgressHUD.showErrorWithStatus("Error:出错拉", maskType: .None) + SVProgressHUD.showErrorWithStatus("Error:出错拉") +// SVProgressHUD.showErrorWithStatus("Error:出错拉", maskType: .None) return } if newError.localizedFailureReason == nil { - SVProgressHUD.showErrorWithStatus("Error:出错拉", maskType: .None) + SVProgressHUD.showErrorWithStatus("Error:出错拉") +// SVProgressHUD.showErrorWithStatus("Error:出错拉", maskType: .None) } else { - SVProgressHUD.showErrorWithStatus(error!.localizedFailureReason, maskType: .None) + SVProgressHUD.showErrorWithStatus(error!.localizedFailureReason) +// SVProgressHUD.showErrorWithStatus(error!.localizedFailureReason, maskType: .None) } break case .ErrorString: - SVProgressHUD.showErrorWithStatus(status, maskType: .None) + SVProgressHUD.showErrorWithStatus(status) +// SVProgressHUD.showErrorWithStatus(status, maskType: .None) break case .Info: - SVProgressHUD.showInfoWithStatus(status, maskType: .None) + SVProgressHUD.showInfoWithStatus(status) +// SVProgressHUD.showInfoWithStatus(status, maskType: .None) break case .Loading: - SVProgressHUD.showWithStatus(status, maskType: .None) + SVProgressHUD.showWithStatus(status) +// SVProgressHUD.showWithStatus(status, maskType: .None) break } } diff --git a/TSWeChat/Vendor/RCActionSheet/RCActionSheet.swift b/TSWeChat/Vendor/RCActionSheet/RCActionSheet.swift new file mode 100644 index 0000000..8168cf1 --- /dev/null +++ b/TSWeChat/Vendor/RCActionSheet/RCActionSheet.swift @@ -0,0 +1,213 @@ + + +import UIKit + + + @objc protocol RCActionSheetDelegate { + optional func actionSheet(actionSheet: RCActionSheet, didClickedWithButtonIndex: Int) + } + + + +class RCActionSheet: UIView { + + let button_height: CGFloat = 49.0 + let screenSize = UIScreen.mainScreen().bounds.size + + private func colorFrom(red: CGFloat, green: CGFloat, blue: CGFloat) -> UIColor { + return UIColor(red: (red)/255.0, green: (green)/255.0, blue: (blue)/255.0, alpha: 1.0) + } + + + var delegate: RCActionSheetDelegate? + private var buttonTitles = [String]() + private var maskBackView = UIView() + private var bottomView = UIView() + private var backWindow: UIWindow? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // public methods + static func actionSheet(title title: String? = nil, buttonTitles: [String], redButtonIndex: Int, delegate: RCActionSheetDelegate? = nil) -> RCActionSheet { + return RCActionSheet(actionTitle: title, buttonTitles: buttonTitles, redButtonIndex: redButtonIndex, delegate: delegate) + } + + convenience init(actionTitle: String? = nil, buttonTitles: [String], redButtonIndex: Int, delegate: RCActionSheetDelegate? = nil) { + self.init() + + self.delegate = delegate + + let backView = UIView(frame: CGRectMake(0, 0, screenSize.width, screenSize.height)) + backView.alpha = 0 + backView.userInteractionEnabled = false + backView.backgroundColor = self.colorFrom(46.0, green: 49.0, blue: 50.0) + self.addSubview(backView) + self.maskBackView = backView + + let tap = UITapGestureRecognizer(target: self, action: Selector("dismiss:")) + backView.addGestureRecognizer(tap) + + let bView = UIView() + bView.backgroundColor = self.colorFrom(233, green: 233, blue: 238) + self.addSubview(bView) + self.bottomView = bView + + + if let titleString = actionTitle { + let titleLabel = UILabel(frame: CGRectMake(0, 0, screenSize.width, button_height)) + titleLabel.text = titleString as String + titleLabel.textColor = self.colorFrom(111, green: 111, blue: 111) + titleLabel.textAlignment = .Center + titleLabel.font = UIFont.systemFontOfSize(13.0) + titleLabel.backgroundColor = UIColor.whiteColor() + bottomView.addSubview(titleLabel) + } + + if buttonTitles.count > 0 { + self.buttonTitles = buttonTitles + + for (index, title) in buttonTitles.enumerate() { + let button = UIButton() + button.tag = index + button.backgroundColor = UIColor.whiteColor() + button.setTitle(title, forState: .Normal) + button.titleLabel?.font = UIFont.systemFontOfSize(16.0) + + var titleColor: UIColor + if index == redButtonIndex { + titleColor = self.colorFrom(255, green: 10, blue: 10) + }else{ + titleColor = UIColor.blackColor() + } + button.setTitleColor(titleColor, forState: .Normal) + + + let backImage = UIImage(named: "bgImage_HL") + button.setBackgroundImage(backImage, forState: .Highlighted) + button.addTarget(self, action: Selector("didClickBtn:"), forControlEvents: .TouchUpInside) + + let a = (actionTitle != nil ? 1 : 0) + let b = a + index + let buttonY = button_height * CGFloat(b) + + button.frame = CGRectMake(0, buttonY, screenSize.width, button_height) + bottomView.addSubview(button) + } + + for (index, _) in buttonTitles.enumerate() { + let lineView = UIImageView(image: UIImage(named: "cellLine")) + lineView.contentMode = .Center + + let a = (actionTitle != nil ? 1 : 0) + let b = a + index + let lineY = button_height * CGFloat(b) + + lineView.frame = CGRectMake(0, lineY, screenSize.width, 1.0) + bottomView.addSubview(lineView) + } + } + + let cancelButton = UIButton() + cancelButton.tag = buttonTitles.count + cancelButton.backgroundColor = UIColor.whiteColor() + cancelButton.setTitle("Cancel", forState: .Normal) + cancelButton.titleLabel?.font = UIFont.systemFontOfSize(16.0) + cancelButton.setTitleColor(UIColor.blackColor(), forState: .Normal) + cancelButton.setBackgroundImage(UIImage(named: "bgImage_HL"), forState: .Highlighted) + cancelButton.addTarget(self, action: Selector("didClickCancelBtn:"), forControlEvents: .TouchUpInside) + + + let a = (actionTitle != nil ? 1 : 0) + let b = a + self.buttonTitles.count + let cancelY = button_height * CGFloat(b) + 5.0 + cancelButton.frame = CGRectMake(0, cancelY, screenSize.width, button_height) + bottomView.addSubview(cancelButton) + + let x = (actionTitle != nil ? button_height : 0) + let bottomH = x + button_height * CGFloat(buttonTitles.count) + button_height + 5 + bottomView.frame = CGRectMake(0, screenSize.height, screenSize.width, bottomH) + + + self.frame = CGRectMake(0, 0, screenSize.width, screenSize.height) + getBackWindow().addSubview(self) + } + + + private func getBackWindow() -> UIWindow{ + if self.backWindow == nil { + let window: UIWindow = UIWindow(frame: UIScreen.mainScreen().bounds) + window.windowLevel = UIWindowLevelStatusBar + window.backgroundColor = UIColor.clearColor() + window.hidden = false + self.backWindow = window + } + + return self.backWindow! + } + + func didClickBtn(button: UIButton) { + dismiss(nil) + + if let rDelegate = self.delegate { + rDelegate.actionSheet!(self, didClickedWithButtonIndex: button.tag) + } + } + + func didClickCancelBtn(button: UIButton){ + UIView.animateWithDuration(0.23, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in + self.maskBackView.alpha = 0 + self.maskBackView.userInteractionEnabled = false + + var frame = self.bottomView.frame + frame.origin.y += frame.size.height + self.bottomView.frame = frame + + }) { (finished) -> Void in + self.getBackWindow().hidden = true + self.removeFromSuperview() + + if let rDelegate = self.delegate { + rDelegate.actionSheet!(self, didClickedWithButtonIndex: self.buttonTitles.count) + } + } + + } + + func dismiss(tap: UITapGestureRecognizer?){ + UIView.animateWithDuration(0.23, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in + self.maskBackView.alpha = 0 + self.maskBackView.userInteractionEnabled = false + + var frame = self.bottomView.frame + frame.origin.y += frame.size.height + self.bottomView.frame = frame + + }) { (finished) -> Void in + self.getBackWindow().hidden = true + self.removeFromSuperview() + } + } + + + + func show(){ + getBackWindow().hidden = false + UIView.animateWithDuration(0.23, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in + self.maskBackView.alpha = 0.4 + self.maskBackView.userInteractionEnabled = true + + var frame = self.bottomView.frame + frame.origin.y -= frame.size.height + self.bottomView.frame = frame + + }) { (finished) -> Void in + print("finished: \(finished)") + } + } +} diff --git a/TSWeChat/Vendor/RCActionSheet/bgImage_HL@2x.png b/TSWeChat/Vendor/RCActionSheet/bgImage_HL@2x.png new file mode 100755 index 0000000..b887b95 Binary files /dev/null and b/TSWeChat/Vendor/RCActionSheet/bgImage_HL@2x.png differ diff --git a/TSWeChat/Vendor/RCActionSheet/cellLine@2x.png b/TSWeChat/Vendor/RCActionSheet/cellLine@2x.png new file mode 100755 index 0000000..1e4987f Binary files /dev/null and b/TSWeChat/Vendor/RCActionSheet/cellLine@2x.png differ