diff --git a/Yep/Caches/AvatarCache.swift b/Yep/Caches/AvatarCache.swift index 31aeba5c..59dfbc1c 100644 --- a/Yep/Caches/AvatarCache.swift +++ b/Yep/Caches/AvatarCache.swift @@ -198,8 +198,9 @@ class AvatarCache { func roundAvatarWithAvatarURLString(avatarURLString: String, withRadius radius: CGFloat, completion: (UIImage) -> ()) { + completion(defaultRoundAvatarOfRadius(radius)) + if avatarURLString.isEmpty { - completion(defaultRoundAvatarOfRadius(radius)) return } @@ -242,7 +243,6 @@ class AvatarCache { } } default: - completion(defaultRoundAvatarOfRadius(radius)) break } } @@ -334,12 +334,13 @@ class AvatarCache { func roundAvatarOfUser(user: User, withRadius radius: CGFloat, completion: (UIImage) -> ()) { + completion(defaultRoundAvatarOfRadius(radius)) + // 为下面切换线程准备,Realm 不能跨线程访问 let avatarURLString = user.avatarURLString let userID = user.userID if avatarURLString.isEmpty { - completion(defaultRoundAvatarOfRadius(radius)) return } @@ -382,7 +383,6 @@ class AvatarCache { } } default: - completion(defaultRoundAvatarOfRadius(radius)) break } } diff --git a/Yep/ViewControllers/Conversation/ConversationViewController.swift b/Yep/ViewControllers/Conversation/ConversationViewController.swift index 7b1c04fe..723aed6c 100644 --- a/Yep/ViewControllers/Conversation/ConversationViewController.swift +++ b/Yep/ViewControllers/Conversation/ConversationViewController.swift @@ -1899,14 +1899,6 @@ extension ConversationViewController: UICollectionViewDataSource, UICollectionVi let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatSectionDateCellIdentifier, forIndexPath: indexPath) as! ChatSectionDateCell - let createdAt = NSDate(timeIntervalSince1970: message.createdUnixTime) - - if createdAt.isInCurrentWeek() { - cell.sectionDateLabel.text = sectionDateInCurrentWeekFormatter.stringFromDate(createdAt) - } else { - cell.sectionDateLabel.text = sectionDateFormatter.stringFromDate(createdAt) - } - return cell } @@ -1922,88 +1914,24 @@ extension ConversationViewController: UICollectionViewDataSource, UICollectionVi let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftImageCellIdentifier, forIndexPath: indexPath) as! ChatLeftImageCell - cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in - - if message.downloadState == MessageDownloadState.Downloaded.rawValue { - self?.performSegueWithIdentifier("showMessageMedia", sender: message) - - } else { - YepAlert.alertSorry(message: NSLocalizedString("Please wait while the image is not dready!", comment: ""), inViewController: self) - } - - }, collectionView: collectionView, indexPath: indexPath) - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell case MessageMediaType.Audio.rawValue: let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftAudioCellIdentifier, forIndexPath: indexPath) as! ChatLeftAudioCell - let audioPlayedDuration = audioPlayedDurationOfMessage(message) - - cell.configureWithMessage(message, audioPlayedDuration: audioPlayedDuration, audioBubbleTapAction: { [weak self] in - - if message.downloadState == MessageDownloadState.Downloaded.rawValue { - self?.playMessageAudioWithMessage(message) - - } else { - YepAlert.alertSorry(message: NSLocalizedString("Please wait while the audio is not dready!", comment: ""), inViewController: self) - } - - }, collectionView: collectionView, indexPath: indexPath) - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell case MessageMediaType.Video.rawValue: let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftVideoCellIdentifier, forIndexPath: indexPath) as! ChatLeftVideoCell - cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in - - if message.downloadState == MessageDownloadState.Downloaded.rawValue { - self?.performSegueWithIdentifier("showMessageMedia", sender: message) - - } else { - YepAlert.alertSorry(message: NSLocalizedString("Please wait while the video is not dready!", comment: ""), inViewController: self) - } - - }, collectionView: collectionView, indexPath: indexPath) - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell case MessageMediaType.Location.rawValue: let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftLocationCellIdentifier, forIndexPath: indexPath) as! ChatLeftLocationCell - cell.configureWithMessage(message, mediaTapAction: { [weak self] in - if let coordinate = message.coordinate { - let locationCoordinate = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude) - let mapItem = MKMapItem(placemark: MKPlacemark(coordinate: locationCoordinate, addressDictionary: nil)) - /* - let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving] - mapItem.openInMapsWithLaunchOptions(launchOptions) - */ - mapItem.openInMapsWithLaunchOptions(nil) - } - - }, collectionView: collectionView, indexPath: indexPath) - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell default: @@ -2012,10 +1940,6 @@ extension ConversationViewController: UICollectionViewDataSource, UICollectionVi cell.configureWithMessage(message, textContentLabelWidth: textContentLabelWidthOfMessage(message), collectionView: collectionView, indexPath: indexPath) - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell } @@ -2027,251 +1951,30 @@ extension ConversationViewController: UICollectionViewDataSource, UICollectionVi let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightImageCellIdentifier, forIndexPath: indexPath) as! ChatRightImageCell - cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in - - if message.sendState == MessageSendState.Failed.rawValue { - - YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend image?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { - - resendMessage(message, failureHandler: { [weak self] reason, errorMessage in - defaultFailureHandler(reason, errorMessage) - - YepAlert.alertSorry(message: NSLocalizedString("Failed to resend image!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) - - }, completion: { success in - println("resendImage: \(success)") - }) - - }, cancelAction: { - }) - - } else { - self?.performSegueWithIdentifier("showMessageMedia", sender: message) - } - - }, collectionView: collectionView, indexPath: indexPath) - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell case MessageMediaType.Audio.rawValue: let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightAudioCellIdentifier, forIndexPath: indexPath) as! ChatRightAudioCell - let audioPlayedDuration = audioPlayedDurationOfMessage(message) - - cell.configureWithMessage(message, audioPlayedDuration: audioPlayedDuration, audioBubbleTapAction: { [weak self] in - - if message.sendState == MessageSendState.Failed.rawValue { - - YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend audio?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { - - resendMessage(message, failureHandler: { [weak self] reason, errorMessage in - defaultFailureHandler(reason, errorMessage) - - YepAlert.alertSorry(message: NSLocalizedString("Failed to resend audio!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) - - }, completion: { success in - println("resendAudio: \(success)") - }) - - }, cancelAction: { - }) - - return - } - - self?.playMessageAudioWithMessage(message) - - }, collectionView: collectionView, indexPath: indexPath) - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell case MessageMediaType.Video.rawValue: let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightVideoCellIdentifier, forIndexPath: indexPath) as! ChatRightVideoCell - cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in - - if message.sendState == MessageSendState.Failed.rawValue { - - YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend video?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { - - resendMessage(message, failureHandler: { [weak self] reason, errorMessage in - defaultFailureHandler(reason, errorMessage) - - YepAlert.alertSorry(message: NSLocalizedString("Failed to resend video!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) - - }, completion: { success in - println("resendVideo: \(success)") - }) - - }, cancelAction: { - }) - - } else { - self?.performSegueWithIdentifier("showMessageMedia", sender: message) - } - - }, collectionView: collectionView, indexPath: indexPath) - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell case MessageMediaType.Location.rawValue: let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightLocationCellIdentifier, forIndexPath: indexPath) as! ChatRightLocationCell - cell.configureWithMessage(message, mediaTapAction: { [weak self] in - - if message.sendState == MessageSendState.Failed.rawValue { - - YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend location?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { - - resendMessage(message, failureHandler: { [weak self] reason, errorMessage in - defaultFailureHandler(reason, errorMessage) - - YepAlert.alertSorry(message: NSLocalizedString("Failed to resend location!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) - - }, completion: { success in - println("resendLocation: \(success)") - }) - - }, cancelAction: { - }) - - } else { - if let coordinate = message.coordinate { - let locationCoordinate = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude) - let mapItem = MKMapItem(placemark: MKPlacemark(coordinate: locationCoordinate, addressDictionary: nil)) - /* - let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving] - mapItem.openInMapsWithLaunchOptions(launchOptions) - */ - mapItem.openInMapsWithLaunchOptions(nil) - } - } - - }, collectionView: collectionView, indexPath: indexPath) - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell default: let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightTextCellIdentifier, forIndexPath: indexPath) as! ChatRightTextCell - cell.configureWithMessage(message, textContentLabelWidth: textContentLabelWidthOfMessage(message), mediaTapAction: { [weak self] in - - if message.sendState == MessageSendState.Failed.rawValue { - - YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend text?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { - - resendMessage(message, failureHandler: { [weak self] reason, errorMessage in - defaultFailureHandler(reason, errorMessage) - - YepAlert.alertSorry(message: NSLocalizedString("Failed to resend text!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) - - }, completion: { success in - println("resendText: \(success)") - }) - - }, cancelAction: { - }) - } - }, collectionView: collectionView, indexPath: indexPath) - - cell.longPressAction = { [weak self] in - dispatch_async(dispatch_get_main_queue()) { - if let strongSelf = self, realm = message.realm { - - var sectionDateMessage: Message? - - if let currentMessageIndex = strongSelf.messages.indexOf(message) { - - let previousMessageIndex = currentMessageIndex - 1 - - if let previousMessage = strongSelf.messages[safe: previousMessageIndex] { - - if previousMessage.mediaType == MessageMediaType.SectionDate.rawValue { - sectionDateMessage = previousMessage - } - } - } - - let currentIndexPath: NSIndexPath - if let index = strongSelf.messages.indexOf(message) { - currentIndexPath = NSIndexPath(forItem: index - strongSelf.displayedMessagesRange.location, inSection: indexPath.section) - } else { - currentIndexPath = indexPath - } - - if let sectionDateMessage = sectionDateMessage { - - var canDeleteTwoMessages = false // 考虑刚好的边界情况,例如消息为本束的最后一条,而 sectionDate 在上一束中 - if strongSelf.displayedMessagesRange.length >= 2 { - strongSelf.displayedMessagesRange.length -= 2 - canDeleteTwoMessages = true - - } else { - if strongSelf.displayedMessagesRange.location >= 1 { - strongSelf.displayedMessagesRange.location -= 1 - } - strongSelf.displayedMessagesRange.length -= 1 - } - - realm.write { - if let mediaMetaData = sectionDateMessage.mediaMetaData { - realm.delete(mediaMetaData) - } - if let mediaMetaData = message.mediaMetaData { - realm.delete(mediaMetaData) - } - realm.delete(sectionDateMessage) - realm.delete(message) - } - - if canDeleteTwoMessages { - let previousIndexPath = NSIndexPath(forItem: currentIndexPath.item - 1, inSection: currentIndexPath.section) - strongSelf.conversationCollectionView.deleteItemsAtIndexPaths([previousIndexPath, currentIndexPath]) - } else { - strongSelf.conversationCollectionView.deleteItemsAtIndexPaths([currentIndexPath]) - } - - } else { - strongSelf.displayedMessagesRange.length -= 1 - realm.write { - if let mediaMetaData = message.mediaMetaData { - realm.delete(mediaMetaData) - } - realm.delete(message) - } - strongSelf.conversationCollectionView.deleteItemsAtIndexPaths([currentIndexPath]) - } - - // 必须更新,插入时需要 - strongSelf.lastTimeMessagesCount = strongSelf.messages.count - } - } - } - - cell.tapAvatarAction = { [weak self] user in - self?.performSegueWithIdentifier("showProfile", sender: user) - } - return cell } } @@ -2288,6 +1991,350 @@ extension ConversationViewController: UICollectionViewDataSource, UICollectionVi } + func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) { + + if let message = messages[safe: (displayedMessagesRange.location + indexPath.item)] { + + if message.mediaType == MessageMediaType.SectionDate.rawValue { + + if let cell = cell as? ChatSectionDateCell { + let createdAt = NSDate(timeIntervalSince1970: message.createdUnixTime) + + if createdAt.isInCurrentWeek() { + cell.sectionDateLabel.text = sectionDateInCurrentWeekFormatter.stringFromDate(createdAt) + } else { + cell.sectionDateLabel.text = sectionDateFormatter.stringFromDate(createdAt) + } + } + + return + } + + if let sender = message.fromFriend { + + if let cell = cell as? ChatBaseCell { + cell.tapAvatarAction = { [weak self] user in + self?.performSegueWithIdentifier("showProfile", sender: user) + } + } + + if sender.friendState != UserFriendState.Me.rawValue { // from Friend + + markMessageAsReaded(message) + + switch message.mediaType { + + case MessageMediaType.Image.rawValue: + + if let cell = cell as? ChatLeftImageCell { + + cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in + + if message.downloadState == MessageDownloadState.Downloaded.rawValue { + self?.performSegueWithIdentifier("showMessageMedia", sender: message) + + } else { + YepAlert.alertSorry(message: NSLocalizedString("Please wait while the image is not dready!", comment: ""), inViewController: self) + } + + }, collectionView: collectionView, indexPath: indexPath) + } + + case MessageMediaType.Audio.rawValue: + + if let cell = cell as? ChatLeftAudioCell { + + let audioPlayedDuration = audioPlayedDurationOfMessage(message) + + cell.configureWithMessage(message, audioPlayedDuration: audioPlayedDuration, audioBubbleTapAction: { [weak self] in + + if message.downloadState == MessageDownloadState.Downloaded.rawValue { + self?.playMessageAudioWithMessage(message) + + } else { + YepAlert.alertSorry(message: NSLocalizedString("Please wait while the audio is not dready!", comment: ""), inViewController: self) + } + + }, collectionView: collectionView, indexPath: indexPath) + } + + case MessageMediaType.Video.rawValue: + + if let cell = cell as? ChatLeftVideoCell { + + cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in + + if message.downloadState == MessageDownloadState.Downloaded.rawValue { + self?.performSegueWithIdentifier("showMessageMedia", sender: message) + + } else { + YepAlert.alertSorry(message: NSLocalizedString("Please wait while the video is not dready!", comment: ""), inViewController: self) + } + + }, collectionView: collectionView, indexPath: indexPath) + } + + case MessageMediaType.Location.rawValue: + + if let cell = cell as? ChatLeftLocationCell { + + cell.configureWithMessage(message, mediaTapAction: { [weak self] in + if let coordinate = message.coordinate { + let locationCoordinate = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude) + let mapItem = MKMapItem(placemark: MKPlacemark(coordinate: locationCoordinate, addressDictionary: nil)) + /* + let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving] + mapItem.openInMapsWithLaunchOptions(launchOptions) + */ + mapItem.openInMapsWithLaunchOptions(nil) + } + + }, collectionView: collectionView, indexPath: indexPath) + } + + default: + + if let cell = cell as? ChatLeftTextCell { + + cell.configureWithMessage(message, textContentLabelWidth: textContentLabelWidthOfMessage(message), collectionView: collectionView, indexPath: indexPath) + } + } + + } else { // from Me + + switch message.mediaType { + + case MessageMediaType.Image.rawValue: + + if let cell = cell as? ChatRightImageCell { + + cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in + + if message.sendState == MessageSendState.Failed.rawValue { + + YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend image?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { + + resendMessage(message, failureHandler: { [weak self] reason, errorMessage in + defaultFailureHandler(reason, errorMessage) + + YepAlert.alertSorry(message: NSLocalizedString("Failed to resend image!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) + + }, completion: { success in + println("resendImage: \(success)") + }) + + }, cancelAction: { + }) + + } else { + self?.performSegueWithIdentifier("showMessageMedia", sender: message) + } + + }, collectionView: collectionView, indexPath: indexPath) + } + + case MessageMediaType.Audio.rawValue: + + if let cell = cell as? ChatRightAudioCell { + + let audioPlayedDuration = audioPlayedDurationOfMessage(message) + + cell.configureWithMessage(message, audioPlayedDuration: audioPlayedDuration, audioBubbleTapAction: { [weak self] in + + if message.sendState == MessageSendState.Failed.rawValue { + + YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend audio?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { + + resendMessage(message, failureHandler: { [weak self] reason, errorMessage in + defaultFailureHandler(reason, errorMessage) + + YepAlert.alertSorry(message: NSLocalizedString("Failed to resend audio!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) + + }, completion: { success in + println("resendAudio: \(success)") + }) + + }, cancelAction: { + }) + + return + } + + self?.playMessageAudioWithMessage(message) + + }, collectionView: collectionView, indexPath: indexPath) + } + + case MessageMediaType.Video.rawValue: + + if let cell = cell as? ChatRightVideoCell { + + cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in + + if message.sendState == MessageSendState.Failed.rawValue { + + YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend video?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { + + resendMessage(message, failureHandler: { [weak self] reason, errorMessage in + defaultFailureHandler(reason, errorMessage) + + YepAlert.alertSorry(message: NSLocalizedString("Failed to resend video!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) + + }, completion: { success in + println("resendVideo: \(success)") + }) + + }, cancelAction: { + }) + + } else { + self?.performSegueWithIdentifier("showMessageMedia", sender: message) + } + + }, collectionView: collectionView, indexPath: indexPath) + } + + case MessageMediaType.Location.rawValue: + + if let cell = cell as? ChatRightLocationCell { + + cell.configureWithMessage(message, mediaTapAction: { [weak self] in + + if message.sendState == MessageSendState.Failed.rawValue { + + YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend location?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { + + resendMessage(message, failureHandler: { [weak self] reason, errorMessage in + defaultFailureHandler(reason, errorMessage) + + YepAlert.alertSorry(message: NSLocalizedString("Failed to resend location!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) + + }, completion: { success in + println("resendLocation: \(success)") + }) + + }, cancelAction: { + }) + + } else { + if let coordinate = message.coordinate { + let locationCoordinate = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude) + let mapItem = MKMapItem(placemark: MKPlacemark(coordinate: locationCoordinate, addressDictionary: nil)) + /* + let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving] + mapItem.openInMapsWithLaunchOptions(launchOptions) + */ + mapItem.openInMapsWithLaunchOptions(nil) + } + } + + }, collectionView: collectionView, indexPath: indexPath) + } + + default: + + if let cell = cell as? ChatRightTextCell { + + cell.configureWithMessage(message, textContentLabelWidth: textContentLabelWidthOfMessage(message), mediaTapAction: { [weak self] in + + if message.sendState == MessageSendState.Failed.rawValue { + + YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend text?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: { + + resendMessage(message, failureHandler: { [weak self] reason, errorMessage in + defaultFailureHandler(reason, errorMessage) + + YepAlert.alertSorry(message: NSLocalizedString("Failed to resend text!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self) + + }, completion: { success in + println("resendText: \(success)") + }) + + }, cancelAction: { + }) + } + }, collectionView: collectionView, indexPath: indexPath) + + cell.longPressAction = { [weak self] in + dispatch_async(dispatch_get_main_queue()) { + if let strongSelf = self, realm = message.realm { + + var sectionDateMessage: Message? + + if let currentMessageIndex = strongSelf.messages.indexOf(message) { + + let previousMessageIndex = currentMessageIndex - 1 + + if let previousMessage = strongSelf.messages[safe: previousMessageIndex] { + + if previousMessage.mediaType == MessageMediaType.SectionDate.rawValue { + sectionDateMessage = previousMessage + } + } + } + + let currentIndexPath: NSIndexPath + if let index = strongSelf.messages.indexOf(message) { + currentIndexPath = NSIndexPath(forItem: index - strongSelf.displayedMessagesRange.location, inSection: indexPath.section) + } else { + currentIndexPath = indexPath + } + + if let sectionDateMessage = sectionDateMessage { + + var canDeleteTwoMessages = false // 考虑刚好的边界情况,例如消息为本束的最后一条,而 sectionDate 在上一束中 + if strongSelf.displayedMessagesRange.length >= 2 { + strongSelf.displayedMessagesRange.length -= 2 + canDeleteTwoMessages = true + + } else { + if strongSelf.displayedMessagesRange.location >= 1 { + strongSelf.displayedMessagesRange.location -= 1 + } + strongSelf.displayedMessagesRange.length -= 1 + } + + realm.write { + if let mediaMetaData = sectionDateMessage.mediaMetaData { + realm.delete(mediaMetaData) + } + if let mediaMetaData = message.mediaMetaData { + realm.delete(mediaMetaData) + } + realm.delete(sectionDateMessage) + realm.delete(message) + } + + if canDeleteTwoMessages { + let previousIndexPath = NSIndexPath(forItem: currentIndexPath.item - 1, inSection: currentIndexPath.section) + strongSelf.conversationCollectionView.deleteItemsAtIndexPaths([previousIndexPath, currentIndexPath]) + } else { + strongSelf.conversationCollectionView.deleteItemsAtIndexPaths([currentIndexPath]) + } + + } else { + strongSelf.displayedMessagesRange.length -= 1 + realm.write { + if let mediaMetaData = message.mediaMetaData { + realm.delete(mediaMetaData) + } + realm.delete(message) + } + strongSelf.conversationCollectionView.deleteItemsAtIndexPaths([currentIndexPath]) + } + + // 必须更新,插入时需要 + strongSelf.lastTimeMessagesCount = strongSelf.messages.count + } + } + } + } + } + } + } + } + } + func collectionView(collectionView: UICollectionView!, layout collectionViewLayout: UICollectionViewLayout!, sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize { if let message = messages[safe: (displayedMessagesRange.location + indexPath.item)] { diff --git a/Yep/ViewControllers/Login/LoginByMobileViewController.swift b/Yep/ViewControllers/Login/LoginByMobileViewController.swift index 7596d47e..175e0b1f 100644 --- a/Yep/ViewControllers/Login/LoginByMobileViewController.swift +++ b/Yep/ViewControllers/Login/LoginByMobileViewController.swift @@ -41,7 +41,7 @@ class LoginByMobileViewController: BaseViewController { areaCodeTextField.delegate = self areaCodeTextField.addTarget(self, action: "textFieldDidChange:", forControlEvents: .EditingChanged) - mobileNumberTextField.placeholder = nil + //mobileNumberTextField.placeholder = "" mobileNumberTextField.delegate = self mobileNumberTextField.addTarget(self, action: "textFieldDidChange:", forControlEvents: .EditingChanged) diff --git a/Yep/ViewControllers/Login/LoginVerifyMobileViewController.swift b/Yep/ViewControllers/Login/LoginVerifyMobileViewController.swift index 0315bdc8..7627b786 100644 --- a/Yep/ViewControllers/Login/LoginVerifyMobileViewController.swift +++ b/Yep/ViewControllers/Login/LoginVerifyMobileViewController.swift @@ -55,10 +55,12 @@ class LoginVerifyMobileViewController: UIViewController { navigationItem.rightBarButtonItem = nextButton + NSNotificationCenter.defaultCenter().addObserver(self, selector: "activeAgain:", name: AppDelegate.Notification.applicationDidBecomeActive, object: nil) + verifyMobileNumberPromptLabel.text = NSLocalizedString("Input verification code send to", comment: "") phoneNumberLabel.text = "+" + areaCode + " " + mobile - verifyCodeTextField.placeholder = nil + //verifyCodeTextField.placeholder = "" verifyCodeTextField.delegate = self verifyCodeTextField.addTarget(self, action: "textFieldDidChange:", forControlEvents: .EditingChanged) @@ -87,6 +89,10 @@ class LoginVerifyMobileViewController: UIViewController { // MARK: Actions + func activeAgain(notification: NSNotification) { + verifyCodeTextField.becomeFirstResponder() + } + func tryCallMe(timer: NSTimer) { if !haveAppropriateInput { if callMeInSeconds > 1 { @@ -200,13 +206,15 @@ class LoginVerifyMobileViewController: UIViewController { } extension LoginVerifyMobileViewController: UITextFieldDelegate { - + + /* func textFieldShouldReturn(textField: UITextField) -> Bool { - if !textField.text.isEmpty { + if haveAppropriateInput { login() } return true } + */ } diff --git a/Yep/ViewControllers/Register/RegisterPickMobileViewController.swift b/Yep/ViewControllers/Register/RegisterPickMobileViewController.swift index 8c86a9f6..541cc616 100644 --- a/Yep/ViewControllers/Register/RegisterPickMobileViewController.swift +++ b/Yep/ViewControllers/Register/RegisterPickMobileViewController.swift @@ -39,7 +39,7 @@ class RegisterPickMobileViewController: UIViewController { areaCodeTextField.delegate = self areaCodeTextField.addTarget(self, action: "textFieldDidChange:", forControlEvents: .EditingChanged) - mobileNumberTextField.placeholder = nil + //mobileNumberTextField.placeholder = "" mobileNumberTextField.delegate = self mobileNumberTextField.addTarget(self, action: "textFieldDidChange:", forControlEvents: .EditingChanged) diff --git a/Yep/ViewControllers/Register/RegisterPickNameViewController.swift b/Yep/ViewControllers/Register/RegisterPickNameViewController.swift index b85c4818..6a915865 100644 --- a/Yep/ViewControllers/Register/RegisterPickNameViewController.swift +++ b/Yep/ViewControllers/Register/RegisterPickNameViewController.swift @@ -63,7 +63,7 @@ class RegisterPickNameViewController: BaseViewController { let tap = UITapGestureRecognizer(target: self, action: "tapTerms") promptTermsLabel.addGestureRecognizer(tap) - nameTextField.placeholder = nil + //nameTextField.placeholder = "" nameTextField.delegate = self nameTextField.addTarget(self, action: "textFieldDidChange:", forControlEvents: .EditingChanged) diff --git a/Yep/ViewControllers/Register/RegisterVerifyMobileViewController.swift b/Yep/ViewControllers/Register/RegisterVerifyMobileViewController.swift index cc74ce42..48d7971d 100644 --- a/Yep/ViewControllers/Register/RegisterVerifyMobileViewController.swift +++ b/Yep/ViewControllers/Register/RegisterVerifyMobileViewController.swift @@ -55,10 +55,12 @@ class RegisterVerifyMobileViewController: UIViewController { navigationItem.rightBarButtonItem = nextButton + NSNotificationCenter.defaultCenter().addObserver(self, selector: "activeAgain:", name: AppDelegate.Notification.applicationDidBecomeActive, object: nil) + verifyMobileNumberPromptLabel.text = NSLocalizedString("Input verification code send to", comment: "") phoneNumberLabel.text = "+" + areaCode + " " + mobile - verifyCodeTextField.placeholder = nil + //verifyCodeTextField.placeholder = "" verifyCodeTextField.delegate = self verifyCodeTextField.addTarget(self, action: "textFieldDidChange:", forControlEvents: .EditingChanged) @@ -87,6 +89,10 @@ class RegisterVerifyMobileViewController: UIViewController { // MARK: Actions + func activeAgain(notification: NSNotification) { + verifyCodeTextField.becomeFirstResponder() + } + func tryCallMe(timer: NSTimer) { if !haveAppropriateInput { if callMeInSeconds > 1 { @@ -195,13 +201,15 @@ class RegisterVerifyMobileViewController: UIViewController { } extension RegisterVerifyMobileViewController: UITextFieldDelegate { - + + /* func textFieldShouldReturn(textField: UITextField) -> Bool { - if !textField.text.isEmpty { + if haveAppropriateInput { verifyRegisterMobile() } return true } + */ }