mirror of
https://github.com/wahyd4/Yep.git
synced 2026-08-22 19:28:54 +10:00
Merge branch 'develop' of https://github.com/CatchChat/Yep into develop
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)] {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user