Apply message bubble view to message details view.
This commit is contained in:
parent
d99a2be005
commit
6830d4e8cb
|
@ -154,6 +154,7 @@
|
||||||
347850711FDAEB17007B8332 /* OWSUserProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3478506F1FDAEB16007B8332 /* OWSUserProfile.m */; };
|
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, ); }; };
|
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 */; };
|
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 */; };
|
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */; };
|
||||||
34A910601FFEB114000C4745 /* OWSBackup.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A9105F1FFEB114000C4745 /* OWSBackup.m */; };
|
34A910601FFEB114000C4745 /* OWSBackup.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A9105F1FFEB114000C4745 /* OWSBackup.m */; };
|
||||||
34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B0796B1FCF46B000E248C2 /* MainAppContext.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
34A9105E1FFEB113000C4745 /* OWSBackup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSBackup.h; sourceTree = "<group>"; };
|
||||||
|
@ -1590,8 +1592,10 @@
|
||||||
34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */,
|
34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */,
|
||||||
34B3F8541E8DF1700035BE1A /* NewGroupViewController.h */,
|
34B3F8541E8DF1700035BE1A /* NewGroupViewController.h */,
|
||||||
34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */,
|
34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */,
|
||||||
|
3496744E2076ACCE00080B5F /* LongTextViewController.swift */,
|
||||||
34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */,
|
34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */,
|
||||||
34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */,
|
34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */,
|
||||||
|
45D2AC01204885170033C692 /* OWS2FAReminderViewController.swift */,
|
||||||
345BC30A2047030600257B7C /* OWS2FASettingsViewController.h */,
|
345BC30A2047030600257B7C /* OWS2FASettingsViewController.h */,
|
||||||
345BC30B2047030600257B7C /* OWS2FASettingsViewController.m */,
|
345BC30B2047030600257B7C /* OWS2FASettingsViewController.m */,
|
||||||
34C42D591F45F7A80072EC04 /* OWSNavigationController.h */,
|
34C42D591F45F7A80072EC04 /* OWSNavigationController.h */,
|
||||||
|
@ -1604,7 +1608,6 @@
|
||||||
34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */,
|
34B3F86E1E8DF1700035BE1A /* SignalsNavigationController.m */,
|
||||||
340FC897204DAC8D007AEB0F /* ThreadSettings */,
|
340FC897204DAC8D007AEB0F /* ThreadSettings */,
|
||||||
34D1F0BE1F8EC1760066283D /* Utils */,
|
34D1F0BE1F8EC1760066283D /* Utils */,
|
||||||
45D2AC01204885170033C692 /* OWS2FAReminderViewController.swift */,
|
|
||||||
);
|
);
|
||||||
path = ViewControllers;
|
path = ViewControllers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3183,6 +3186,7 @@
|
||||||
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */,
|
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */,
|
||||||
340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */,
|
340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */,
|
||||||
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
|
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
|
||||||
|
3496744F2076ACD000080B5F /* LongTextViewController.swift in Sources */,
|
||||||
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */,
|
34FD93701E3BD43A00109093 /* OWSAnyTouchGestureRecognizer.m in Sources */,
|
||||||
34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */,
|
34B3F8931E8DF1710035BE1A /* SignalsNavigationController.m in Sources */,
|
||||||
34D1F0AC1F867BFC0066283D /* OWSExpirationTimerView.m in Sources */,
|
34D1F0AC1F867BFC0066283D /* OWSExpirationTimerView.m in Sources */,
|
||||||
|
|
|
@ -2101,11 +2101,7 @@ typedef enum : NSUInteger {
|
||||||
OWSAssert(conversationItem);
|
OWSAssert(conversationItem);
|
||||||
OWSAssert([conversationItem.interaction isKindOfClass:[TSMessage class]]);
|
OWSAssert([conversationItem.interaction isKindOfClass:[TSMessage class]]);
|
||||||
|
|
||||||
TSMessage *message = (TSMessage *)conversationItem.interaction;
|
LongTextViewController *view = [[LongTextViewController alloc] initWithViewItem:conversationItem];
|
||||||
MessageDetailViewController *view =
|
|
||||||
[[MessageDetailViewController alloc] initWithViewItem:conversationItem
|
|
||||||
message:message
|
|
||||||
mode:MessageMetadataViewModeFocusOnMessage];
|
|
||||||
[self.navigationController pushViewController:view animated:YES];
|
[self.navigationController pushViewController:view animated:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -493,28 +493,6 @@ class MessageDetailViewController: OWSViewController, MediaDetailPresenter, Medi
|
||||||
AttachmentSharing.showShareUI(forAttachment: attachmentStream)
|
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
|
// MARK: - Actions
|
||||||
|
|
||||||
// This method should be called after self.databaseConnection.beginLongLivedReadTransaction().
|
// This method should be called after self.databaseConnection.beginLongLivedReadTransaction().
|
||||||
|
@ -633,6 +611,8 @@ class MessageDetailViewController: OWSViewController, MediaDetailPresenter, Medi
|
||||||
case .default:
|
case .default:
|
||||||
break
|
break
|
||||||
case .oversizeText:
|
case .oversizeText:
|
||||||
|
let viewController = LongTextViewController(viewItem: viewItem)
|
||||||
|
self.navigationController?.pushViewController(viewController, animated: true)
|
||||||
break
|
break
|
||||||
case .media:
|
case .media:
|
||||||
// TODO: Show/play media.
|
// TODO: Show/play media.
|
||||||
|
|
|
@ -971,6 +971,9 @@
|
||||||
/* No comment provided by engineer. */
|
/* No comment provided by engineer. */
|
||||||
"LOGGING_SECTION" = "Logging";
|
"LOGGING_SECTION" = "Logging";
|
||||||
|
|
||||||
|
/* Title for the 'long text message' view. */
|
||||||
|
"LONG_TEXT_VIEW_TITLE" = "Message";
|
||||||
|
|
||||||
/* nav bar button item */
|
/* nav bar button item */
|
||||||
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "All Media";
|
"MEDIA_DETAIL_VIEW_ALL_MEDIA_BUTTON" = "All Media";
|
||||||
|
|
||||||
|
@ -1010,9 +1013,6 @@
|
||||||
/* Label for the MIME type of attachments in the 'message metadata' view. */
|
/* Label for the MIME type of attachments in the 'message metadata' view. */
|
||||||
"MESSAGE_METADATA_VIEW_ATTACHMENT_MIME_TYPE" = "MIME type";
|
"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. */
|
/* Label for 'not yet downloaded' attachments in the 'message metadata' view. */
|
||||||
"MESSAGE_METADATA_VIEW_ATTACHMENT_NOT_YET_DOWNLOADED" = "Not yet downloaded";
|
"MESSAGE_METADATA_VIEW_ATTACHMENT_NOT_YET_DOWNLOADED" = "Not yet downloaded";
|
||||||
|
|
||||||
|
|
|
@ -217,20 +217,20 @@ extension String {
|
||||||
@objc
|
@objc
|
||||||
public class func displayableText(_ rawText: String) -> DisplayableText {
|
public class func displayableText(_ rawText: String) -> DisplayableText {
|
||||||
// Only show up to N characters of text.
|
// Only show up to N characters of text.
|
||||||
let kMaxTextDisplayLength = 1024
|
let kMaxTextDisplayLength = 512
|
||||||
let fullText = rawText.filterStringForDisplay()
|
let fullText = rawText.filterStringForDisplay()
|
||||||
var isTextTruncated = false
|
var isTextTruncated = false
|
||||||
var displayText = fullText
|
var displayText = fullText
|
||||||
if displayText.count > kMaxTextDisplayLength {
|
if displayText.count > kMaxTextDisplayLength {
|
||||||
// Trim whitespace before _AND_ after slicing the snipper from the string.
|
// Trim whitespace before _AND_ after slicing the snipper from the string.
|
||||||
let snippet = String(displayText.prefix(kMaxTextDisplayLength)).ows_stripped()
|
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."),
|
"A display format for oversize text messages."),
|
||||||
snippet)
|
snippet)
|
||||||
isTextTruncated = true
|
isTextTruncated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let displayableText = DisplayableText(fullText: fullText, displayText: displayText, isTextTruncated:isTextTruncated)
|
let displayableText = DisplayableText(fullText: fullText, displayText: displayText, isTextTruncated: isTextTruncated)
|
||||||
return displayableText
|
return displayableText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue