Apply message bubble view to message details view.

This commit is contained in:
Matthew Chen 2018-04-05 15:55:59 -04:00
parent d99a2be005
commit 6830d4e8cb
6 changed files with 114 additions and 34 deletions

View File

@ -154,6 +154,7 @@
347850711FDAEB17007B8332 /* OWSUserProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3478506F1FDAEB16007B8332 /* OWSUserProfile.m */; };
347850721FDAEB17007B8332 /* OWSUserProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 347850701FDAEB16007B8332 /* OWSUserProfile.h */; settings = {ATTRIBUTES = (Public, ); }; };
3496744D2076768700080B5F /* OWSMessageBubbleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3496744C2076768700080B5F /* OWSMessageBubbleView.m */; };
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3496744E2076ACCE00080B5F /* LongTextViewController.swift */; };
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */; };
34A910601FFEB114000C4745 /* OWSBackup.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A9105F1FFEB114000C4745 /* OWSBackup.m */; };
34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B0796B1FCF46B000E248C2 /* MainAppContext.m */; };
@ -729,6 +730,7 @@
3495BC911F1426B800B478F5 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = translations/ar.lproj/Localizable.strings; sourceTree = "<group>"; };
3496744B2076768600080B5F /* OWSMessageBubbleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSMessageBubbleView.h; sourceTree = "<group>"; };
3496744C2076768700080B5F /* OWSMessageBubbleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSMessageBubbleView.m; sourceTree = "<group>"; };
3496744E2076ACCE00080B5F /* LongTextViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LongTextViewController.swift; sourceTree = "<group>"; };
34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS2FARegistrationViewController.m; sourceTree = "<group>"; };
34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS2FARegistrationViewController.h; sourceTree = "<group>"; };
34A9105E1FFEB113000C4745 /* OWSBackup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackup.h; sourceTree = "<group>"; };
@ -1590,8 +1592,10 @@
34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */,
34B3F8541E8DF1700035BE1A /* NewGroupViewController.h */,
34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */,
3496744E2076ACCE00080B5F /* LongTextViewController.swift */,
34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */,
34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */,
45D2AC01204885170033C692 /* OWS2FAReminderViewController.swift */,
345BC30A2047030600257B7C /* OWS2FASettingsViewController.h */,
345BC30B2047030600257B7C /* OWS2FASettingsViewController.m */,
34C42D591F45F7A80072EC04 /* OWSNavigationController.h */,
@ -1604,7 +1608,6 @@
34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */,
340FC897204DAC8D007AEB0F /* ThreadSettings */,
34D1F0BE1F8EC1760066283D /* Utils */,
45D2AC01204885170033C692 /* OWS2FAReminderViewController.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
@ -3183,6 +3186,7 @@
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */,
340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */,
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */,
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */,
34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */,
34D1F0AC1F867BFC0066283D /* OWSExpirationTimerView.m in Sources */,

View File

@ -2101,11 +2101,7 @@ typedef enum : NSUInteger {
OWSAssert(conversationItem);
OWSAssert([conversationItem.interaction isKindOfClass:[TSMessage class]]);
TSMessage *message = (TSMessage *)conversationItem.interaction;
MessageDetailViewController *view =
[[MessageDetailViewController alloc] initWithViewItem:conversationItem
message:message
mode:MessageMetadataViewModeFocusOnMessage];
LongTextViewController *view = [[LongTextViewController alloc] initWithViewItem:conversationItem];
[self.navigationController pushViewController:view animated:YES];
}

View File

@ -0,0 +1,100 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
import SignalServiceKit
import SignalMessaging
@objc
public class LongTextViewController: OWSViewController {
// MARK: Properties
let viewItem: ConversationViewItem
let messageBody: String
var messageTextView: UITextView?
// MARK: Initializers
@available(*, unavailable, message:"use other constructor instead.")
public required init?(coder aDecoder: NSCoder) {
fatalError("\(#function) is unimplemented.")
}
public required init(viewItem: ConversationViewItem) {
self.viewItem = viewItem
self.messageBody = LongTextViewController.displayableText(viewItem: viewItem)
super.init(nibName: nil, bundle: nil)
}
private class func displayableText(viewItem: ConversationViewItem) -> String {
guard viewItem.hasBodyText else {
return ""
}
guard let displayableText = viewItem.displayableBodyText() else {
return ""
}
let messageBody = displayableText.fullText
return messageBody
}
// MARK: View Lifecycle
public override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = NSLocalizedString("LONG_TEXT_VIEW_TITLE",
comment: "Title for the 'long text message' view.")
createViews()
}
// MARK: - Create Views
private func createViews() {
view.backgroundColor = UIColor.white
let messageTextView = UITextView()
self.messageTextView = messageTextView
messageTextView.font = UIFont.ows_dynamicTypeBody
messageTextView.backgroundColor = UIColor.white
messageTextView.isOpaque = true
messageTextView.isEditable = false
messageTextView.isSelectable = true
messageTextView.isScrollEnabled = true
messageTextView.showsHorizontalScrollIndicator = false
messageTextView.showsVerticalScrollIndicator = true
messageTextView.isUserInteractionEnabled = true
messageTextView.textColor = UIColor.black
messageTextView.text = messageBody
view.addSubview(messageTextView)
messageTextView.autoPinLeadingToSuperviewMargin()
messageTextView.autoPinTrailingToSuperviewMargin()
messageTextView.autoPin(toTopLayoutGuideOf: self, withInset: 0)
let footer = UIToolbar()
footer.barTintColor = UIColor.ows_materialBlue
view.addSubview(footer)
footer.autoPinWidthToSuperview(withMargin: 0)
footer.autoPinEdge(.top, to: .bottom, of: messageTextView)
footer.autoPin(toBottomLayoutGuideOf: self, withInset: 0)
footer.items = [
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareButtonPressed)),
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
]
}
// MARK: - Actions
func shareButtonPressed() {
AttachmentSharing.showShareUI(forText: messageBody)
}
}

View File

@ -493,28 +493,6 @@ class MessageDetailViewController: OWSViewController, MediaDetailPresenter, Medi
AttachmentSharing.showShareUI(forAttachment: attachmentStream)
}
func copyToPasteboard() {
if let messageBody = messageBody {
UIPasteboard.general.string = messageBody
return
}
guard let attachmentStream = attachmentStream else {
Logger.error("\(logTag) Message has neither attachment nor message body.")
return
}
guard let utiType = MIMETypeUtil.utiType(forMIMEType: attachmentStream.contentType) else {
Logger.error("\(logTag) Attachment has invalid MIME type: \(attachmentStream.contentType).")
return
}
guard let dataSource = dataSource else {
Logger.error("\(logTag) Attachment missing data source.")
return
}
let data = dataSource.data()
UIPasteboard.general.setData(data, forPasteboardType: utiType)
}
// MARK: - Actions
// This method should be called after self.databaseConnection.beginLongLivedReadTransaction().
@ -633,6 +611,8 @@ class MessageDetailViewController: OWSViewController, MediaDetailPresenter, Medi
case .default:
break
case .oversizeText:
let viewController = LongTextViewController(viewItem: viewItem)
self.navigationController?.pushViewController(viewController, animated: true)
break
case .media:
// TODO: Show/play media.

View File

@ -971,6 +971,9 @@
/* No comment provided by engineer. */
"LOGGING_SECTION" = "Logging";
/* Title for the 'long text message' view. */
"LONG_TEXT_VIEW_TITLE" = "Message";
/* nav bar button item */
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "All Media";
@ -1010,9 +1013,6 @@
/* Label for the MIME type of attachments in the 'message metadata' view. */
"MESSAGE_METADATA_VIEW_ATTACHMENT_MIME_TYPE" = "MIME type";
/* Label for 'missing' attachments in the 'message metadata' view. */
"MESSAGE_METADATA_VIEW_ATTACHMENT_MISSING_FILE" = "Missing Attachment";
/* Label for 'not yet downloaded' attachments in the 'message metadata' view. */
"MESSAGE_METADATA_VIEW_ATTACHMENT_NOT_YET_DOWNLOADED" = "Not yet downloaded";

View File

@ -217,20 +217,20 @@ extension String {
@objc
public class func displayableText(_ rawText: String) -> DisplayableText {
// Only show up to N characters of text.
let kMaxTextDisplayLength = 1024
let kMaxTextDisplayLength = 512
let fullText = rawText.filterStringForDisplay()
var isTextTruncated = false
var displayText = fullText
if displayText.count > kMaxTextDisplayLength {
// Trim whitespace before _AND_ after slicing the snipper from the string.
let snippet = String(displayText.prefix(kMaxTextDisplayLength)).ows_stripped()
displayText = String(format:NSLocalizedString("OVERSIZE_TEXT_DISPLAY_FORMAT", comment:
displayText = String(format: NSLocalizedString("OVERSIZE_TEXT_DISPLAY_FORMAT", comment:
"A display format for oversize text messages."),
snippet)
isTextTruncated = true
}
let displayableText = DisplayableText(fullText: fullText, displayText: displayText, isTextTruncated:isTextTruncated)
let displayableText = DisplayableText(fullText: fullText, displayText: displayText, isTextTruncated: isTextTruncated)
return displayableText
}
}