Fix remaining TODOs

This commit is contained in:
Niels Andriesse 2020-12-07 15:11:49 +11:00
parent 61611db58e
commit 3f5bc18f6b
15 changed files with 216 additions and 46 deletions

View File

@ -1454,9 +1454,9 @@ typedef enum : NSUInteger {
// Do nothing // Do nothing
} }
- (void)handleUnsentMessageTap:(TSOutgoingMessage *)message - (void)handleUnsentMessageTap:(TSOutgoingMessage *)tsMessage
{ {
UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:message.mostRecentFailureText UIAlertController *actionSheet = [UIAlertController alertControllerWithTitle:tsMessage.mostRecentFailureText
message:nil message:nil
preferredStyle:UIAlertControllerStyleActionSheet]; preferredStyle:UIAlertControllerStyleActionSheet];
@ -1465,23 +1465,29 @@ typedef enum : NSUInteger {
UIAlertAction *deleteMessageAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"") UIAlertAction *deleteMessageAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"")
style:UIAlertActionStyleDestructive style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) { handler:^(UIAlertAction *action) {
[self remove:message]; [self remove:tsMessage];
}]; }];
[actionSheet addAction:deleteMessageAction]; [actionSheet addAction:deleteMessageAction];
// TODO TODO TODO UIAlertAction *resendMessageAction = [UIAlertAction
actionWithTitle:NSLocalizedString(@"SEND_AGAIN_BUTTON", @"")
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"send_again")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
SNVisibleMessage *message = [SNVisibleMessage from:tsMessage];
[LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSMutableArray<TSAttachmentStream *> *attachments = @[].mutableCopy;
for (NSString *attachmentID in tsMessage.attachmentIds) {
TSAttachmentStream *stream = [TSAttachmentStream fetchObjectWithUniqueID:attachmentID transaction:transaction];
if (![stream isKindOfClass:TSAttachmentStream.class]) { continue; }
[attachments addObject:stream];
}
[SNMessageSender prep:attachments forMessage:message usingTransaction: transaction];
[SNMessageSender send:message inThread:self.thread usingTransaction:transaction];
}];
}];
// UIAlertAction *resendMessageAction = [UIAlertAction [actionSheet addAction:resendMessageAction];
// actionWithTitle:NSLocalizedString(@"SEND_AGAIN_BUTTON", @"")
// accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"send_again")
// style:UIAlertActionStyleDefault
// handler:^(UIAlertAction *action) {
// [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
// [self.messageSenderJobQueue addMessage:message transaction:transaction];
// }];
// }];
// [actionSheet addAction:resendMessageAction];
[self dismissKeyBoard]; [self dismissKeyBoard];
[self presentAlert:actionSheet]; [self presentAlert:actionSheet];

View File

@ -6,11 +6,20 @@ public final class ClosedGroupUpdate : ControlMessage {
public var kind: Kind? public var kind: Kind?
// MARK: Kind // MARK: Kind
public enum Kind { public enum Kind : CustomStringConvertible {
case new(groupPublicKey: Data, name: String, groupPrivateKey: Data, senderKeys: [ClosedGroupSenderKey], members: [Data], admins: [Data]) case new(groupPublicKey: Data, name: String, groupPrivateKey: Data, senderKeys: [ClosedGroupSenderKey], members: [Data], admins: [Data])
case info(groupPublicKey: Data, name: String, senderKeys: [ClosedGroupSenderKey], members: [Data], admins: [Data]) case info(groupPublicKey: Data, name: String, senderKeys: [ClosedGroupSenderKey], members: [Data], admins: [Data])
case senderKeyRequest(groupPublicKey: Data) case senderKeyRequest(groupPublicKey: Data)
case senderKey(groupPublicKey: Data, senderKey: ClosedGroupSenderKey) case senderKey(groupPublicKey: Data, senderKey: ClosedGroupSenderKey)
public var description: String {
switch self {
case .new: return "new"
case .info: return "info"
case .senderKeyRequest: return "senderKeyRequest"
case .senderKey: return "senderKey"
}
}
} }
// MARK: Initialization // MARK: Initialization
@ -154,6 +163,15 @@ public final class ClosedGroupUpdate : ControlMessage {
return nil return nil
} }
} }
// MARK: Description
public override var description: String {
"""
ClosedGroupUpdate(
kind: \(kind?.description ?? "null")
)
"""
}
} }
private extension ClosedGroupSenderKey { private extension ClosedGroupSenderKey {

View File

@ -56,6 +56,15 @@ public final class ExpirationTimerUpdate : ControlMessage {
} }
} }
// MARK: Description
public override var description: String {
"""
ExpirationTimerUpdate(
duration: \(duration?.description ?? "null")
)
"""
}
// MARK: Convenience // MARK: Convenience
@objc public func setDuration(_ duration: UInt32) { @objc public func setDuration(_ duration: UInt32) {
self.duration = duration self.duration = duration

View File

@ -54,4 +54,13 @@ public final class ReadReceipt : ControlMessage {
return nil return nil
} }
} }
// MARK: Description
public override var description: String {
"""
ReadReceipt(
timestamps: \(timestamps?.description ?? "null")
)
"""
}
} }

View File

@ -7,7 +7,7 @@ public final class TypingIndicator : ControlMessage {
public override class var ttl: UInt64 { 30 * 1000 } public override class var ttl: UInt64 { 30 * 1000 }
// MARK: Kind // MARK: Kind
public enum Kind : Int { public enum Kind : Int, CustomStringConvertible {
case started, stopped case started, stopped
static func fromProto(_ proto: SNProtoTypingMessage.SNProtoTypingMessageAction) -> Kind { static func fromProto(_ proto: SNProtoTypingMessage.SNProtoTypingMessageAction) -> Kind {
@ -23,6 +23,13 @@ public final class TypingIndicator : ControlMessage {
case .stopped: return .stopped case .stopped: return .stopped
} }
} }
public var description: String {
switch self {
case .started: return "started"
case .stopped: return "stopped"
}
}
} }
// MARK: Validation // MARK: Validation
@ -72,4 +79,13 @@ public final class TypingIndicator : ControlMessage {
return nil return nil
} }
} }
// MARK: Description
public override var description: String {
"""
TypingIndicator(
kind: \(kind?.description ?? "null")
)
"""
}
} }

View File

@ -1,3 +1,4 @@
import SessionUtilitiesKit
@objc public extension TSOutgoingMessage { @objc public extension TSOutgoingMessage {
@ -21,3 +22,23 @@
) )
} }
} }
@objc public extension VisibleMessage {
@objc(from:)
static func from(_ tsMessage: TSOutgoingMessage) -> VisibleMessage {
let result = VisibleMessage()
result.threadID = tsMessage.uniqueThreadId
result.sentTimestamp = tsMessage.timestamp
result.recipient = tsMessage.recipientIds().first
if let thread = tsMessage.thread as? TSGroupThread, thread.usesSharedSenderKeys {
let groupID = thread.groupModel.groupId
result.groupPublicKey = LKGroupUtilities.getDecodedGroupID(groupID)
}
result.text = tsMessage.body
result.attachmentIDs = tsMessage.attachmentIds.compactMap { $0 as? String }
result.quote = VisibleMessage.Quote.from(tsMessage.quotedMessage)
result.linkPreview = VisibleMessage.LinkPreview.from(tsMessage.linkPreview)
return result
}
}

View File

@ -56,5 +56,16 @@ public extension VisibleMessage {
return nil return nil
} }
} }
// MARK: Description
public override var description: String {
"""
LinkPreview(
title: \(title ?? "null")
url: \(url ?? "null")
attachmentID: \(attachmentID ?? "null")
)
"""
}
} }
} }

View File

@ -57,5 +57,16 @@ public extension VisibleMessage {
return nil return nil
} }
} }
// MARK: Description
public override var description: String {
"""
Profile(
displayName: \(displayName ?? "null")
profileKey: \(profileKey?.description ?? "null")
profilePictureURL: \(profilePictureURL ?? "null")
)
"""
}
} }
} }

View File

@ -66,8 +66,9 @@ public extension VisibleMessage {
guard let stream = TSAttachmentStream.fetch(uniqueId: attachmentID, transaction: transaction), stream.isUploaded else { guard let stream = TSAttachmentStream.fetch(uniqueId: attachmentID, transaction: transaction), stream.isUploaded else {
#if DEBUG #if DEBUG
preconditionFailure("Sending a message before all associated attachments have been uploaded.") preconditionFailure("Sending a message before all associated attachments have been uploaded.")
#endif #else
return return
#endif
} }
let quotedAttachmentProto = SNProtoDataMessageQuoteQuotedAttachment.builder() let quotedAttachmentProto = SNProtoDataMessageQuoteQuotedAttachment.builder()
quotedAttachmentProto.setContentType(stream.contentType) quotedAttachmentProto.setContentType(stream.contentType)
@ -82,5 +83,17 @@ public extension VisibleMessage {
SNLog("Couldn't construct quoted attachment proto from: \(self).") SNLog("Couldn't construct quoted attachment proto from: \(self).")
} }
} }
// MARK: Description
public override var description: String {
"""
Quote(
timestamp: \(timestamp?.description ?? "null")
publicKey: \(publicKey ?? "null")
text: \(text ?? "null")
attachmentID: \(attachmentID ?? "null")
)
"""
}
} }
} }

View File

@ -99,4 +99,18 @@ public final class VisibleMessage : Message {
return nil return nil
} }
} }
// MARK: Description
public override var description: String {
"""
VisibleMessage(
text: \(text ?? "null")
attachmentIDs: \(attachmentIDs)
quote: \(quote?.description ?? "null")
linkPreview: \(linkPreview?.description ?? "null")
contact: \(contact?.description ?? "null")
profile: \(profile?.description ?? "null")
)
"""
}
} }

View File

@ -9,6 +9,11 @@ extension OWSLinkPreview {
extension VisibleMessage.LinkPreview { extension VisibleMessage.LinkPreview {
public static func from(_ linkPreview: OWSLinkPreview?) -> VisibleMessage.LinkPreview? {
guard let linkPreview = linkPreview else { return nil }
return VisibleMessage.LinkPreview(title: linkPreview.title, url: linkPreview.urlString!, attachmentID: linkPreview.imageAttachmentId)
}
@objc(from:using:) @objc(from:using:)
public static func from(_ linkPreview: OWSLinkPreviewDraft?, using transaction: YapDatabaseReadWriteTransaction) -> VisibleMessage.LinkPreview? { public static func from(_ linkPreview: OWSLinkPreviewDraft?, using transaction: YapDatabaseReadWriteTransaction) -> VisibleMessage.LinkPreview? {
guard let linkPreview = linkPreview else { return nil } guard let linkPreview = linkPreview else { return nil }

View File

@ -59,6 +59,19 @@ public final class MessageSender : NSObject {
attachment.write($0.dataSource) attachment.write($0.dataSource)
attachment.save(with: transaction) attachment.save(with: transaction)
} }
prep(attachments, for: message, using: transaction)
}
@objc(prep:forMessage:usingTransaction:)
public static func prep(_ attachmentStreams: [TSAttachmentStream], for message: VisibleMessage, using transaction: YapDatabaseReadWriteTransaction) {
guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else {
#if DEBUG
preconditionFailure()
#else
return
#endif
}
var attachments = attachmentStreams
// The line below locally generates a thumbnail for the quoted attachment. It just needs to happen at some point during the // The line below locally generates a thumbnail for the quoted attachment. It just needs to happen at some point during the
// message sending process. // message sending process.
tsMessage.quotedMessage?.createThumbnailAttachmentsIfNecessary(with: transaction) tsMessage.quotedMessage?.createThumbnailAttachmentsIfNecessary(with: transaction)
@ -71,6 +84,7 @@ public final class MessageSender : NSObject {
// Anything added to message.attachmentIDs will be uploaded by an UploadAttachmentJob. Any attachment IDs added to tsMessage will // Anything added to message.attachmentIDs will be uploaded by an UploadAttachmentJob. Any attachment IDs added to tsMessage will
// make it render as an attachment (not what we want in the case of a link preview or quoted attachment). // make it render as an attachment (not what we want in the case of a link preview or quoted attachment).
message.attachmentIDs = attachments.map { $0.uniqueId! } message.attachmentIDs = attachments.map { $0.uniqueId! }
tsMessage.attachmentIds.removeAllObjects()
tsMessage.attachmentIds.addObjects(from: message.attachmentIDs) tsMessage.attachmentIds.addObjects(from: message.attachmentIDs)
if let id = linkPreviewAttachmentID { tsMessage.attachmentIds.remove(id) } if let id = linkPreviewAttachmentID { tsMessage.attachmentIds.remove(id) }
tsMessage.save(with: transaction) tsMessage.save(with: transaction)
@ -109,7 +123,9 @@ public final class MessageSender : NSObject {
func handleFailure(with error: Swift.Error, using transaction: YapDatabaseReadWriteTransaction) { func handleFailure(with error: Swift.Error, using transaction: YapDatabaseReadWriteTransaction) {
MessageSender.handleFailedMessageSend(message, with: error, using: transaction) MessageSender.handleFailedMessageSend(message, with: error, using: transaction)
if case .contact(_) = destination, message is VisibleMessage, !isSelfSend { if case .contact(_) = destination, message is VisibleMessage, !isSelfSend {
NotificationCenter.default.post(name: .messageSendingFailed, object: NSNumber(value: message.sentTimestamp!)) DispatchQueue.main.async {
NotificationCenter.default.post(name: .messageSendingFailed, object: NSNumber(value: message.sentTimestamp!))
}
} }
seal.reject(error) seal.reject(error)
} }
@ -217,7 +233,9 @@ public final class MessageSender : NSObject {
guard !isSuccess else { return } // Succeed as soon as the first promise succeeds guard !isSuccess else { return } // Succeed as soon as the first promise succeeds
isSuccess = true isSuccess = true
if case .contact(_) = destination, message is VisibleMessage, !isSelfSend { if case .contact(_) = destination, message is VisibleMessage, !isSelfSend {
NotificationCenter.default.post(name: .messageSent, object: NSNumber(value: message.sentTimestamp!)) DispatchQueue.main.async {
NotificationCenter.default.post(name: .messageSent, object: NSNumber(value: message.sentTimestamp!))
}
} }
storage.withAsync({ transaction in storage.withAsync({ transaction in
MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction) MessageSender.handleSuccessfulMessageSend(message, to: destination, using: transaction)

View File

@ -16,3 +16,16 @@ extension TSQuotedMessage {
) )
} }
} }
extension VisibleMessage.Quote {
public static func from(_ quote: TSQuotedMessage?) -> VisibleMessage.Quote? {
guard let quote = quote else { return nil }
let result = VisibleMessage.Quote()
result.timestamp = quote.timestamp
result.publicKey = quote.authorId
result.text = quote.body
result.attachmentID = quote.quotedAttachments.first?.attachmentId
return result
}
}

View File

@ -22,6 +22,11 @@ extension MessageSender {
return AnyPromise.from(sendNonDurably(message, with: attachments, in: thread, using: transaction)) return AnyPromise.from(sendNonDurably(message, with: attachments, in: thread, using: transaction))
} }
@objc(sendNonDurably:withAttachmentIDs:inThread:usingTransaction:)
public static func objc_sendNonDurably(_ message: VisibleMessage, with attachmentIDs: [String], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> AnyPromise {
return AnyPromise.from(sendNonDurably(message, with: attachmentIDs, in: thread, using: transaction))
}
@objc(sendNonDurably:inThread:usingTransaction:) @objc(sendNonDurably:inThread:usingTransaction:)
public static func objc_sendNonDurably(_ message: Message, in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> AnyPromise { public static func objc_sendNonDurably(_ message: Message, in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> AnyPromise {
return AnyPromise.from(sendNonDurably(message, in: thread, using: transaction)) return AnyPromise.from(sendNonDurably(message, in: thread, using: transaction))
@ -29,7 +34,11 @@ extension MessageSender {
public static func sendNonDurably(_ message: VisibleMessage, with attachments: [SignalAttachment], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> Promise<Void> { public static func sendNonDurably(_ message: VisibleMessage, with attachments: [SignalAttachment], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> Promise<Void> {
prep(attachments, for: message, using: transaction) prep(attachments, for: message, using: transaction)
let attachments = message.attachmentIDs.compactMap { TSAttachmentStream.fetch(uniqueId: $0, transaction: transaction) } return sendNonDurably(message, with: message.attachmentIDs, in: thread, using: transaction)
}
public static func sendNonDurably(_ message: VisibleMessage, with attachmentIDs: [String], in thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) -> Promise<Void> {
let attachments = attachmentIDs.compactMap { TSAttachmentStream.fetch(uniqueId: $0, transaction: transaction) }
let attachmentsToUpload = attachments.filter { !$0.isUploaded } let attachmentsToUpload = attachments.filter { !$0.isUploaded }
let attachmentUploadPromises: [Promise<Void>] = attachmentsToUpload.map { stream in let attachmentUploadPromises: [Promise<Void>] = attachmentsToUpload.map { stream in
let openGroup = SNMessagingKitConfiguration.shared.storage.getOpenGroup(for: thread.uniqueId!) let openGroup = SNMessagingKitConfiguration.shared.storage.getOpenGroup(for: thread.uniqueId!)

View File

@ -414,10 +414,10 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion);
}); });
} }
- (void)resendMessage:(TSOutgoingMessage *)message fromViewController:(UIViewController *)fromViewController - (void)resendMessage:(TSOutgoingMessage *)tsMessage fromViewController:(UIViewController *)fromViewController
{ {
OWSAssertIsOnMainThread(); OWSAssertIsOnMainThread();
OWSAssertDebug(message); OWSAssertDebug(tsMessage);
OWSAssertDebug(fromViewController); OWSAssertDebug(fromViewController);
NSString *progressTitle = NSLocalizedString(@"SHARE_EXTENSION_SENDING_IN_PROGRESS_TITLE", @"Alert title"); NSString *progressTitle = NSLocalizedString(@"SHARE_EXTENSION_SENDING_IN_PROGRESS_TITLE", @"Alert title");
@ -434,29 +434,26 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion);
[fromViewController [fromViewController
presentAlert:progressAlert presentAlert:progressAlert
completion:^{ completion:^{
SNVisibleMessage *message = [SNVisibleMessage from:tsMessage];
// TODO TODO TODO [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
NSMutableArray<TSAttachmentStream *> *attachments = @[].mutableCopy;
// [self.messageSender sendMessage:message for (NSString *attachmentID in tsMessage.attachmentIds) {
// success:^{ TSAttachmentStream *stream = [TSAttachmentStream fetchObjectWithUniqueID:attachmentID transaction:transaction];
// OWSLogInfo(@"Resending attachment succeeded."); if (![stream isKindOfClass:TSAttachmentStream.class]) { continue; }
// dispatch_async(dispatch_get_main_queue(), ^{ [attachments addObject:stream];
// [self.shareViewDelegate shareViewWasCompleted]; }
// }); [SNMessageSender prep:attachments forMessage:message usingTransaction: transaction];
// } [SNMessageSender sendNonDurably:message withAttachmentIDs:tsMessage.attachmentIds inThread:self.thread usingTransaction:transaction]
// failure:^(NSError *error) { .thenOn(dispatch_get_main_queue(), ^() {
// dispatch_async(dispatch_get_main_queue(), ^{ [self.shareViewDelegate shareViewWasCompleted];
// [fromViewController })
// dismissViewControllerAnimated:YES .catchOn(dispatch_get_main_queue(), ^(NSError *error) {
// completion:^{ [fromViewController dismissViewControllerAnimated:YES completion:^{
// OWSLogInfo(@"Sending attachment failed with error: %@", error); [self showSendFailureAlertWithError:error message:tsMessage fromViewController:fromViewController];
// [self showSendFailureAlertWithError:error }];
// message:message });
// fromViewController:fromViewController]; }];
// }];
// });
// }];
}]; }];
} }