From 4649fcfd20e883eea1b08acc710b3f85f4ada2d7 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 29 Mar 2017 12:20:28 -0400 Subject: [PATCH] Add "oversize test message" view. // FREEBIE --- Signal.xcodeproj/project.pbxproj | 4 + Signal/src/Signal-Bridging-Header.h | 3 + .../view controllers/MessagesViewController.m | 10 +- .../OversizeTextMessageViewController.swift | 150 ++++++++++++++++++ .../translations/en.lproj/Localizable.strings | 9 ++ 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 Signal/src/view controllers/OversizeTextMessageViewController.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 85cadd6f9..307c797d1 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 34535D821E256BE9008A4747 /* UIView+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 34535D811E256BE9008A4747 /* UIView+OWS.m */; }; 345671011E89A5F1006EE662 /* ThreadUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 345671001E89A5F1006EE662 /* ThreadUtil.m */; }; 3456710A1E8A9F5D006EE662 /* TSGenericAttachmentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 345671091E8A9F5D006EE662 /* TSGenericAttachmentAdapter.m */; }; + 345671231E8B1618006EE662 /* OversizeTextMessageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 345671221E8B1618006EE662 /* OversizeTextMessageViewController.swift */; }; 34802DD71E899CFB0032EA1D /* DebugUITableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34802DD61E899CFB0032EA1D /* DebugUITableViewController.m */; }; 348A08421E6A044E0057E290 /* MessagesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 348A08411E6A044E0057E290 /* MessagesViewController.xib */; }; 348A08441E6A1D2C0057E290 /* OWSMessagesToolbarContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 348A08431E6A1D2C0057E290 /* OWSMessagesToolbarContentView.xib */; }; @@ -407,6 +408,7 @@ 345671001E89A5F1006EE662 /* ThreadUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadUtil.m; sourceTree = ""; }; 345671081E8A9F5D006EE662 /* TSGenericAttachmentAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSGenericAttachmentAdapter.h; sourceTree = ""; }; 345671091E8A9F5D006EE662 /* TSGenericAttachmentAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSGenericAttachmentAdapter.m; sourceTree = ""; }; + 345671221E8B1618006EE662 /* OversizeTextMessageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OversizeTextMessageViewController.swift; sourceTree = ""; }; 34802DD51E899CFB0032EA1D /* DebugUITableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUITableViewController.h; sourceTree = ""; }; 34802DD61E899CFB0032EA1D /* DebugUITableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugUITableViewController.m; sourceTree = ""; }; 348A08411E6A044E0057E290 /* MessagesViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessagesViewController.xib; sourceTree = ""; }; @@ -1339,6 +1341,7 @@ 45514DE11DDFA183003EFF90 /* InviteFlow.swift */, B6BADBE51B88D1AC0086A80D /* LockInteractionController.h */, B6BADBE61B88D1AC0086A80D /* LockInteractionController.m */, + 345671221E8B1618006EE662 /* OversizeTextMessageViewController.swift */, 458E382F1D6682450094BD24 /* OWSQRCodeScanningViewController.h */, 458E38301D6682450094BD24 /* OWSQRCodeScanningViewController.m */, FC3196311A08141D0094C78E /* Settings */, @@ -2214,6 +2217,7 @@ 45666EC91D994C0D008FE134 /* OWSGroupAvatarBuilder.m in Sources */, 76EB063018170B33006006FC /* Conversions.m in Sources */, FCAC963C19FEF9280046DFC5 /* SignalsViewController.m in Sources */, + 345671231E8B1618006EE662 /* OversizeTextMessageViewController.swift in Sources */, B66B9F7D1AEAF40500E2E609 /* NotificationSettingsOptionsViewController.m in Sources */, 76EB058218170B33006006FC /* Environment.m in Sources */, 45464DBC1DFA041F001D3FD6 /* DataChannelMessage.swift in Sources */, diff --git a/Signal/src/Signal-Bridging-Header.h b/Signal/src/Signal-Bridging-Header.h index 44b1a54c5..48ad505d8 100644 --- a/Signal/src/Signal-Bridging-Header.h +++ b/Signal/src/Signal-Bridging-Header.h @@ -5,6 +5,7 @@ #import #import "Asserts.h" +#import "AttachmentSharing.h" #import "Environment.h" #import "NotificationsManager.h" #import "OWSAnyTouchGestureRecognizer.h" @@ -49,6 +50,8 @@ #import #import #import +#import +#import #import #import #import diff --git a/Signal/src/view controllers/MessagesViewController.m b/Signal/src/view controllers/MessagesViewController.m index dc50da9f2..67e014e21 100644 --- a/Signal/src/view controllers/MessagesViewController.m +++ b/Signal/src/view controllers/MessagesViewController.m @@ -1347,7 +1347,7 @@ typedef enum : NSUInteger { { id messageItem = [self messageAtIndexPath:indexPath]; TSInteraction *interaction = [self interactionAtIndexPath:indexPath]; - + switch (messageItem.messageType) { case TSOutgoingMessageAdapter: { TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage *)interaction; @@ -1564,9 +1564,17 @@ typedef enum : NSUInteger { TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentID]; if ([attachment isKindOfClass:[TSAttachmentStream class]]) { TSAttachmentStream *stream = (TSAttachmentStream *)attachment; + // Tapping on incoming and outgoing unknown extensions should show the + // sharing UI. if ([[messageItem media] isKindOfClass:[TSGenericAttachmentAdapter class]]) { [AttachmentSharing showShareUIForAttachment:stream]; } + // Tapping on incoming and outgoing "oversize text messages" should show the + // "oversize text message" view. + if ([attachment.contentType isEqualToString:OWSMimeTypeOversizeTextMessage]) { + OversizeTextMessageViewController *messageVC = [[OversizeTextMessageViewController alloc] initWithMessage:message]; + [self.navigationController pushViewController:messageVC animated:YES]; + } } } } diff --git a/Signal/src/view controllers/OversizeTextMessageViewController.swift b/Signal/src/view controllers/OversizeTextMessageViewController.swift new file mode 100644 index 000000000..3fe5fc627 --- /dev/null +++ b/Signal/src/view controllers/OversizeTextMessageViewController.swift @@ -0,0 +1,150 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +import Foundation +import WebRTC +import PromiseKit + +class OversizeTextMessageViewController: UIViewController { + + let TAG = "[OversizeTextMessageViewController]" + + let message: TSMessage + + // MARK: Initializers + + @available(*, unavailable, message:"use message: constructor instead.") + required init?(coder aDecoder: NSCoder) { + message = TSMessage() + super.init(coder: aDecoder) + } + + required init(message: TSMessage) { + self.message = message + super.init(nibName: nil, bundle: nil) + } + + // MARK: Attachment + + private func attachmentStream() -> TSAttachmentStream? { + guard message.hasAttachments() else { + Logger.error("\(TAG) message has no attachments.") + assert(false) + return nil + } + let attachmentIDRaw = message.attachmentIds[0] + guard attachmentIDRaw is String else { + Logger.error("\(TAG) message attachment id is not a string.") + assert(false) + return nil + } + let attachmentID = attachmentIDRaw as! String + guard let attachment = TSAttachment.fetch(withUniqueID:attachmentID) else { + Logger.error("\(TAG) could not load attachment.") + assert(false) + return nil + } + guard attachment.contentType == OWSMimeTypeOversizeTextMessage else { + Logger.error("\(TAG) attachment has unexpected content type.") + assert(false) + return nil + } + guard attachment is TSAttachmentStream else { + Logger.error("\(TAG) attachment has unexpected type.") + assert(false) + return nil + } + let stream = attachment as! TSAttachmentStream + return stream + } + + private func attachmentData() -> Data? { + guard let stream = attachmentStream() else { + Logger.error("\(TAG) attachment has invalid stream.") + assert(false) + return nil + } + guard let mediaURL = stream.mediaURL() else { + Logger.error("\(TAG) attachment missing URL.") + assert(false) + return nil + } + do { + let textData = try Data(contentsOf:mediaURL) + return textData + } catch { + Logger.error("\(TAG) error loading data.") + assert(false) + return nil + } + } + + private func displayText() -> String { + guard let textData = attachmentData() else { + Logger.error("\(TAG) could not load attachment data.") + assert(false) + return "" + } + guard let fullText = String(data:textData, encoding:.utf8) else { + Logger.error("\(TAG) text is empty.") + assert(false) + return "" + } + guard let displayText = DisplayableTextFilter().displayableText(fullText) else { + Logger.error("\(TAG) No valid text.") + assert(false) + return "" + } + return displayText + } + + // MARK: View Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + + self.navigationItem.title = NSLocalizedString("OVERSIZE_TEXT_MESSAGE_VIEW_TITLE", + comment: "The title of the 'oversize text message' view.") + + self.view.backgroundColor = UIColor.white + + let textView = UITextView() + textView.textColor = UIColor.black + textView.text = displayText() + textView.font = UIFont.ows_regularFont(withSize:14) + self.view.addSubview(textView) + textView.autoPinWidthToSuperview() + textView.autoPin(toTopLayoutGuideOf : self, withInset: 0) + + let footerBar = UIToolbar() + footerBar.barTintColor = UIColor.ows_signalBrandBlue() + footerBar.setItems([ + UIBarButtonItem(barButtonSystemItem:.flexibleSpace, + target:nil, + action:nil), + UIBarButtonItem(barButtonSystemItem:.action, + target:self, + action:#selector(shareWasPressed)), + UIBarButtonItem(barButtonSystemItem:.flexibleSpace, + target:nil, + action:nil) + ], animated: false) + self.view.addSubview(footerBar) + footerBar.autoPinWidthToSuperview() + footerBar.autoPin(toBottomLayoutGuideOf : self, withInset: 0) + footerBar.autoPinEdge(.top, to:.bottom, of:textView) + } + + func shareWasPressed(sender: UIButton) { + Logger.info("\(TAG) sharing oversize text.") + + guard let attachment = attachmentStream() else { + Logger.error("\(TAG) attachment has invalid stream.") + assert(false) + return + } + + AttachmentSharing.showShareUI(for:attachment.mediaURL()) + } +} diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index fdb37bb01..c433fd8ca 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -97,6 +97,12 @@ /* No comment provided by engineer. */ "ATTACHMENT_QUEUED" = "New attachment queued for retrieval."; +/* A message indicating that an attachment of unknown type was received. */ +"ATTACHMENT_UNKNOWN_TYPE" = "Unknown attachment received"; + +/* 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"; + /* Accessibilty label for placing call button */ "CALL_LABEL" = "Call"; @@ -607,6 +613,9 @@ /* A display format for oversize text messages. */ "OVERSIZE_TEXT_DISPLAY_FORMAT" = "%@… [Tap For More]"; +/* The title of the 'oversize text message' view. */ +"OVERSIZE_TEXT_MESSAGE_VIEW_TITLE" = "Message"; + /* Alert body when verifying with {{contact name}} */ "PRIVACY_VERIFICATION_FAILED_I_HAVE_WRONG_KEY_FOR_THEM" = "This doesn't look like your safety number with %@. Are you verifying the correct contact?";