diff --git a/Signal/src/view controllers/MessagesViewController.m b/Signal/src/view controllers/MessagesViewController.m index 7142e9cff..b8595cafe 100644 --- a/Signal/src/view controllers/MessagesViewController.m +++ b/Signal/src/view controllers/MessagesViewController.m @@ -1951,6 +1951,7 @@ typedef enum : NSUInteger { self.tag, __PRETTY_FUNCTION__, attachment ? [attachment errorMessage] : @"Missing data"); + [self showErrorAlertForAttachment:attachment]; failedToPickAttachment(nil); } else { [self sendMessageAttachment:attachment]; @@ -1988,21 +1989,21 @@ typedef enum : NSUInteger { SignalAttachment *attachment = [SignalAttachment imageAttachmentWithData:imageData dataUTI:dataUTI]; - if (!attachment || - [attachment hasError]) { - DDLogWarn(@"%@ %s Invalid attachment: %@.", - self.tag, - __PRETTY_FUNCTION__, - attachment ? [attachment errorMessage] : @"Missing data"); - failedToPickAttachment(nil); - } else { - [self dismissViewControllerAnimated:YES - completion:^{ - OWSAssert([NSThread isMainThread]); - + [self dismissViewControllerAnimated:YES + completion:^{ + OWSAssert([NSThread isMainThread]); + if (!attachment || + [attachment hasError]) { + DDLogWarn(@"%@ %s Invalid attachment: %@.", + self.tag, + __PRETTY_FUNCTION__, + attachment ? [attachment errorMessage] : @"Missing data"); + [self showErrorAlertForAttachment:attachment]; + failedToPickAttachment(nil); + } else { [self sendMessageAttachment:attachment]; - }]; - } + } + }]; }]; } } @@ -2083,7 +2084,7 @@ typedef enum : NSUInteger { self.tag, __PRETTY_FUNCTION__, attachment ? [attachment errorMessage] : @"Missing data"); - // TODO: How should we handle errors here? + [self showErrorAlertForAttachment:attachment]; } else { [self sendMessageAttachment:attachment]; } @@ -2319,7 +2320,7 @@ typedef enum : NSUInteger { self.tag, __PRETTY_FUNCTION__, attachment ? [attachment errorMessage] : @"Missing data"); - // TODO: How should we handle errors here? + [self showErrorAlertForAttachment:attachment]; } else { [self sendMessageAttachment:attachment]; } @@ -2559,13 +2560,13 @@ typedef enum : NSUInteger { self.tag, __PRETTY_FUNCTION__, attachment ? [attachment errorMessage] : @"Missing data"); - // TODO: Add UI. + [self showErrorAlertForAttachment:attachment]; } else { __weak MessagesViewController *weakSelf = self; UIViewController *viewController = [[AttachmentApprovalViewController alloc] initWithAttachment:attachment - successCompletion:^{ - [weakSelf sendMessageAttachment:attachment]; - }]; + successCompletion:^{ + [weakSelf sendMessageAttachment:attachment]; + }]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; [self.navigationController presentViewController:navigationController animated:YES @@ -2573,6 +2574,30 @@ typedef enum : NSUInteger { } } +- (void)showErrorAlertForAttachment:(SignalAttachment * _Nullable)attachment { + OWSAssert(attachment == nil || [attachment hasError]); + + NSString *errorMessage = (attachment + ? [attachment errorMessage] + : [SignalAttachment missingDataErrorMessage]); + + DDLogError(@"%@ %s: %@", + self.tag, + __PRETTY_FUNCTION__, errorMessage); + + UIAlertController *controller = + [UIAlertController alertControllerWithTitle:NSLocalizedString(@"ATTACHMENT_ERROR_ALERT_TITLE", + @"The title of the 'attachment error' alert.") + message:errorMessage + preferredStyle:UIAlertControllerStyleAlert]; + [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) + style:UIAlertActionStyleDefault + handler:nil]]; + [self presentViewController:controller + animated:YES + completion:nil]; +} + #pragma mark - Class methods + (UINib *)nib diff --git a/Signal/src/view controllers/SignalAttachment.swift b/Signal/src/view controllers/SignalAttachment.swift index d240d1aa4..12b20761f 100644 --- a/Signal/src/view controllers/SignalAttachment.swift +++ b/Signal/src/view controllers/SignalAttachment.swift @@ -5,7 +5,7 @@ import Foundation import MobileCoreServices -enum SignalAttachmentError: String { +enum SignalAttachmentError: Int { case missingData case fileSizeTooLarge case invalidData @@ -97,7 +97,25 @@ class SignalAttachment: NSObject { assert(false) return nil } - return "\(error)" + + switch error { + case .missingData: + return NSLocalizedString("ATTACHMENT_ERROR_MISSING_DATA", comment: "Attachment error message for attachments without any data") + case .fileSizeTooLarge: + return NSLocalizedString("ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE", comment: "Attachment error message for attachments whose data exceed file size limits") + case .invalidData: + return NSLocalizedString("ATTACHMENT_ERROR_INVALID_DATA", comment: "Attachment error message for attachments with invalid data") + case .couldNotParseImage: + return NSLocalizedString("ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE", comment: "Attachment error message for image attachments which cannot be parsed") + case .couldNotConvertToJpeg: + return NSLocalizedString("ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG", comment: "Attachment error message for image attachments which could not be converted to JPEG") + case .invalidFileFormat: + return NSLocalizedString("ATTACHMENT_ERROR_INVALID_FILE_FORMAT", comment: "Attachment error message for attachments with an invalid file format") + } + } + + class var missingDataErrorMessage: String { + return NSLocalizedString("ATTACHMENT_ERROR_MISSING_DATA", comment: "Attachment error message for attachments without any data") } // Returns the MIME type for this attachment or nil if no MIME type diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 8574c829d..72d5f5ac7 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -67,6 +67,27 @@ /* No comment provided by engineer. */ "ATTACHMENT_DOWNLOADING" = "Attachment is downloading"; +/* The title of the 'attachment error' alert. */ +"ATTACHMENT_ERROR_ALERT_TITLE" = "Error Sending Attachment"; + +/* Attachment error message for image attachments which could not be converted to JPEG */ +"ATTACHMENT_ERROR_COULD_NOT_CONVERT_TO_JPEG" = "Image attachment could not be resized."; + +/* Attachment error message for image attachments which cannot be parsed */ +"ATTACHMENT_ERROR_COULD_NOT_PARSE_IMAGE" = "Image attachment could not be parsed."; + +/* Attachment error message for attachments whose data exceed file size limits */ +"ATTACHMENT_ERROR_FILE_SIZE_TOO_LARGE" = "Attachment is too large."; + +/* Attachment error message for attachments with invalid data */ +"ATTACHMENT_ERROR_INVALID_DATA" = "Attachment has invalid contents."; + +/* Attachment error message for attachments with an invalid file format */ +"ATTACHMENT_ERROR_INVALID_FILE_FORMAT" = "Attachment has invalid file format."; + +/* Attachment error message for attachments without any data */ +"ATTACHMENT_ERROR_MISSING_DATA" = "Attachment is empty."; + /* Accessibility hint describing what you can do with the attachment button */ "ATTACHMENT_HINT" = "Choose or take a picture and then send it"; @@ -79,9 +100,6 @@ /* No comment provided by engineer. */ "AUDIO_PERMISSION_MESSAGE" = "Signal requires access to your microphone to work properly. You can grant this permission in the Settings app >> Privacy >> Microphone >> Signal"; -/* Title for call interstitial view */ -"CALL_INTERSTITIAL_CALLING_LABEL" = "Calling..."; - /* Accessibilty label for placing call button */ "CALL_LABEL" = "Call"; @@ -412,9 +430,6 @@ /* No comment provided by engineer. */ "INCOMING_INCOMPLETE_CALL" = "Incomplete incoming call from"; -/* Generic error text when message contents are undisplayable */ -"INFO_MESSAGE_UNABLE_TO_DISPLAY_MESSAGE" = "Unable to display message."; - /* Text for button at the top of the contact picker */ "INVITE_FRIENDS_CONTACT_TABLE_BUTTON" = "Invite Friends to Signal"; @@ -934,9 +949,6 @@ /* No comment provided by engineer. */ "TXT_DELETE_TITLE" = "Delete"; -/* Alert Title */ -"UNABLE_TO_PLACE_CALL" = "Unable to place call."; - /* Pressing this button moves an archived thread from the archive back to the inbox */ "UNARCHIVE_ACTION" = "Unarchive";