Implement resending of failed messages

pull/347/head
nielsandriesse 4 years ago
parent 1b60ecf840
commit 81b29394ec

@ -85,40 +85,44 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
} }
func handleViewItemTapped(_ viewItem: ConversationViewItem, gestureRecognizer: UITapGestureRecognizer) { func handleViewItemTapped(_ viewItem: ConversationViewItem, gestureRecognizer: UITapGestureRecognizer) {
switch viewItem.messageCellType { if let message = viewItem.interaction as? TSOutgoingMessage, message.messageState == .failed {
case .audio: playOrPauseAudio(for: viewItem) showFailedMessageSheet(for: message)
case .mediaMessage: } else {
guard let index = viewItems.firstIndex(where: { $0 === viewItem }), switch viewItem.messageCellType {
let cell = messagesTableView.cellForRow(at: IndexPath(row: index, section: 0)) as? VisibleMessageCell, let albumView = cell.albumView else { return } case .audio: playOrPauseAudio(for: viewItem)
let locationInCell = gestureRecognizer.location(in: cell) case .mediaMessage:
if let overlayView = cell.mediaTextOverlayView { guard let index = viewItems.firstIndex(where: { $0 === viewItem }),
let locationInOverlayView = cell.convert(locationInCell, to: overlayView) let cell = messagesTableView.cellForRow(at: IndexPath(row: index, section: 0)) as? VisibleMessageCell, let albumView = cell.albumView else { return }
if let readMoreButton = overlayView.readMoreButton, readMoreButton.frame.contains(locationInOverlayView) { let locationInCell = gestureRecognizer.location(in: cell)
return showFullText(viewItem) // FIXME: Bit of a hack to do it this way if let overlayView = cell.mediaTextOverlayView {
let locationInOverlayView = cell.convert(locationInCell, to: overlayView)
if let readMoreButton = overlayView.readMoreButton, readMoreButton.frame.contains(locationInOverlayView) {
return showFullText(viewItem) // FIXME: Bit of a hack to do it this way
}
} }
} let locationInAlbumView = cell.convert(locationInCell, to: albumView)
let locationInAlbumView = cell.convert(locationInCell, to: albumView) guard let mediaView = albumView.mediaView(forLocation: locationInAlbumView) else { return }
guard let mediaView = albumView.mediaView(forLocation: locationInAlbumView) else { return } if albumView.isMoreItemsView(mediaView: mediaView) && viewItem.mediaAlbumHasFailedAttachment() {
if albumView.isMoreItemsView(mediaView: mediaView) && viewItem.mediaAlbumHasFailedAttachment() {
// TODO: Tapped a failed incoming attachment
}
let attachment = mediaView.attachment
if let pointer = attachment as? TSAttachmentPointer {
if pointer.state == .failed {
// TODO: Tapped a failed incoming attachment // TODO: Tapped a failed incoming attachment
} }
let attachment = mediaView.attachment
if let pointer = attachment as? TSAttachmentPointer {
if pointer.state == .failed {
// TODO: Tapped a failed incoming attachment
}
}
guard let stream = attachment as? TSAttachmentStream else { return }
let gallery = MediaGallery(thread: thread, options: [ .sliderEnabled, .showAllMediaButton ])
gallery.presentDetailView(fromViewController: self, mediaAttachment: stream, replacingView: mediaView)
case .genericAttachment:
guard let url = viewItem.attachmentStream?.originalMediaURL else { return }
let shareVC = UIActivityViewController(activityItems: [ url ], applicationActivities: nil)
navigationController!.present(shareVC, animated: true, completion: nil)
case .textOnlyMessage:
guard let preview = viewItem.linkPreview, let urlAsString = preview.urlString, let url = URL(string: urlAsString) else { return }
openURL(url)
default: break
} }
guard let stream = attachment as? TSAttachmentStream else { return }
let gallery = MediaGallery(thread: thread, options: [ .sliderEnabled, .showAllMediaButton ])
gallery.presentDetailView(fromViewController: self, mediaAttachment: stream, replacingView: mediaView)
case .genericAttachment:
guard let url = viewItem.attachmentStream?.originalMediaURL else { return }
let shareVC = UIActivityViewController(activityItems: [ url ], applicationActivities: nil)
navigationController!.present(shareVC, animated: true, completion: nil)
case .textOnlyMessage:
guard let preview = viewItem.linkPreview, let urlAsString = preview.urlString, let url = URL(string: urlAsString) else { return }
openURL(url)
default: break
} }
} }

@ -4,7 +4,6 @@
// Mentions // Mentions
// Remaining send logic // Remaining send logic
// Subtitle // Subtitle
// Resending failed messages
// Slight paging glitch // Slight paging glitch
// Scrolling bug // Scrolling bug
// Scroll button bug // Scroll button bug
@ -361,6 +360,33 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, UITableViewD
linkPreviewModel.modalTransitionStyle = .crossDissolve linkPreviewModel.modalTransitionStyle = .crossDissolve
present(linkPreviewModel, animated: true, completion: nil) present(linkPreviewModel, animated: true, completion: nil)
} }
func showFailedMessageSheet(for tsMessage: TSOutgoingMessage) {
let thread = self.thread
let sheet = UIAlertController(title: tsMessage.mostRecentFailureText, message: nil, preferredStyle: .actionSheet)
sheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
sheet.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: { _ in
Storage.write { transaction in
tsMessage.remove(with: transaction)
Storage.shared.cancelPendingMessageSendJobIfNeeded(for: tsMessage.timestamp, using: transaction)
}
}))
sheet.addAction(UIAlertAction(title: "Resend", style: .default, handler: { _ in
let message = VisibleMessage.from(tsMessage)
Storage.write { transaction in
var attachments: [TSAttachmentStream] = []
tsMessage.attachmentIds.forEach { attachmentID in
guard let attachmentID = attachmentID as? String else { return }
let attachment = TSAttachment.fetch(uniqueId: attachmentID, transaction: transaction)
guard let stream = attachment as? TSAttachmentStream else { return }
attachments.append(stream)
}
MessageSender.prep(attachments, for: message, using: transaction)
MessageSender.send(message, in: thread, using: transaction)
}
}))
present(sheet, animated: true, completion: nil)
}
// MARK: Convenience // MARK: Convenience
private func getTitle() -> String { private func getTitle() -> String {

@ -480,7 +480,7 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewV2Delegate {
case .read: case .read:
backgroundColor = isLightMode ? .black : .white backgroundColor = isLightMode ? .black : .white
image = isLightMode ? #imageLiteral(resourceName: "FilledCircleCheckLightMode") : #imageLiteral(resourceName: "FilledCircleCheckDarkMode") image = isLightMode ? #imageLiteral(resourceName: "FilledCircleCheckLightMode") : #imageLiteral(resourceName: "FilledCircleCheckDarkMode")
case .failed: image = #imageLiteral(resourceName: "message_status_failed").asTintedImage(color: Colors.text)! case .failed: image = #imageLiteral(resourceName: "message_status_failed").asTintedImage(color: Colors.destructive)!
} }
return (image, backgroundColor) return (image, backgroundColor)
} }

@ -27,7 +27,7 @@ final class LinkPreviewModal : Modal {
let messageLabel = UILabel() let messageLabel = UILabel()
messageLabel.textColor = Colors.text messageLabel.textColor = Colors.text
messageLabel.font = .systemFont(ofSize: Values.smallFontSize) messageLabel.font = .systemFont(ofSize: Values.smallFontSize)
let message = "Session can show previews for URLs. This will make your messaging experience nicer, but to generate a preview Session needs to contact the website in question. You can always disable link previews in the in-app settings." let message = "Enabling link previews will show previews for URLs you send and receive. This can be useful, but Session will need to contact linked websites to generate previews. You can always disable link previews in Session's settings."
messageLabel.text = message messageLabel.text = message
messageLabel.numberOfLines = 0 messageLabel.numberOfLines = 0
messageLabel.lineBreakMode = .byWordWrapping messageLabel.lineBreakMode = .byWordWrapping

Loading…
Cancel
Save