Improve handling of text and url shares.

pull/1/head
Matthew Chen 7 years ago
parent 5770a18b08
commit 979386ee9e

@ -130,8 +130,8 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool
scrollView.autoPinEdgesToSuperviewEdges() scrollView.autoPinEdgesToSuperviewEdges()
let defaultCaption = self.defaultCaption() let defaultCaption = self.defaultCaption()
let isUrlShare = defaultCaption != nil let isTextualShare = defaultCaption != nil
let backgroundColor = isUrlShare ? UIColor.ows_signalBrandBlue : UIColor.black let backgroundColor = isTextualShare ? UIColor.ows_signalBrandBlue : UIColor.black
self.view.backgroundColor = backgroundColor self.view.backgroundColor = backgroundColor
// Create full screen container view so the scrollView // Create full screen container view so the scrollView
@ -237,12 +237,12 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool
} }
private func defaultCaption() -> String? { private func defaultCaption() -> String? {
guard self.attachment.isUrl else { guard self.attachment.isUrl || self.attachment.isText else {
return nil return nil
} }
let data = self.attachment.data let data = self.attachment.data
guard let messageText = String(data: data, encoding: String.Encoding.utf8) else { guard let messageText = String(data: data, encoding: String.Encoding.utf8) else {
Logger.error("\(self.logTag) Couldn't load url strubg") Logger.error("\(self.logTag) Couldn't load url or text string")
return nil return nil
} }
return messageText return messageText

@ -110,10 +110,11 @@ public class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
createVideoPreview() createVideoPreview()
} else if attachment.isAudio { } else if attachment.isAudio {
createAudioPreview() createAudioPreview()
// We handle the isOversizeText case before isText.
} else if attachment.isOversizeText { } else if attachment.isOversizeText {
createOversizeTextPreview()
} else if attachment.isUrl || attachment.isText {
createTextPreview() createTextPreview()
} else if attachment.isUrl {
createUrlPreview()
} else { } else {
createGenericPreview() createGenericPreview()
} }
@ -290,7 +291,7 @@ public class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
} }
} }
private func createTextPreview() { private func createOversizeTextPreview() {
let data = attachment.data let data = attachment.data
guard let messageText = String(data: data, encoding: String.Encoding.utf8) else { guard let messageText = String(data: data, encoding: String.Encoding.utf8) else {
@ -342,7 +343,7 @@ public class MediaMessageView: UIView, OWSAudioAttachmentPlayerDelegate {
messageTextView.autoPinTrailingToSuperview(withMargin:15) messageTextView.autoPinTrailingToSuperview(withMargin:15)
} }
private func createUrlPreview() { private func createTextPreview() {
// Show nothing; URLs should only appear in the attachment approval view // Show nothing; URLs should only appear in the attachment approval view
// of the SAE and in this context the URL will be placed in the caption field. // of the SAE and in this context the URL will be placed in the caption field.
} }

@ -18,6 +18,8 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
typedef void (^SendCompletionBlock)(NSError *_Nullable, TSOutgoingMessage *);
@interface SharingThreadPickerViewController () <SelectThreadViewControllerDelegate, @interface SharingThreadPickerViewController () <SelectThreadViewControllerDelegate,
AttachmentApprovalViewControllerDelegate> AttachmentApprovalViewControllerDelegate>
@ -193,8 +195,7 @@ NS_ASSUME_NONNULL_BEGIN
} }
#endif #endif
void (^sendCompletion)(NSError *_Nullable, TSOutgoingMessage *) = ^( SendCompletionBlock sendCompletion = ^(NSError *_Nullable error, TSOutgoingMessage *message) {
NSError *_Nullable error, TSOutgoingMessage *message) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
if (error) { if (error) {
@ -215,33 +216,46 @@ NS_ASSUME_NONNULL_BEGIN
}); });
}; };
[fromViewController [fromViewController presentViewController:progressAlert
presentViewController:progressAlert animated:YES
animated:YES completion:^(void) {
completion:^(void) { if ((self.attachment.isUrl || self.attachment.isText)
__block TSOutgoingMessage *outgoingMessage = nil; && self.attachment.captionText.length > 0) {
if (self.attachment.isUrl && self.attachment.captionText.length > 0) { // Urls and text shares are added to the caption text, so discard
// Urls are added to the caption text, so discard the attachment // the attachment and send the caption as a regular text message.
// and send the caption as a regular text message. NSString *messageText = self.attachment.captionText;
NSString *messageText = self.attachment.captionText; [self sendAsTextMessage:messageText sendCompletion:sendCompletion];
outgoingMessage = [ThreadUtil sendMessageWithText:messageText } else {
inThread:self.thread [self sendAsAttachmentMessage:sendCompletion];
messageSender:self.messageSender }
success:^{ }];
sendCompletion(nil, outgoingMessage); }
}
failure:^(NSError *_Nonnull error) { - (void)sendAsTextMessage:(NSString *)messageText sendCompletion:(SendCompletionBlock)sendCompletion
sendCompletion(error, outgoingMessage); {
}]; OWSAssert(messageText.length > 0);
} else {
outgoingMessage = [ThreadUtil sendMessageWithAttachment:self.attachment __block TSOutgoingMessage *outgoingMessage = nil;
inThread:self.thread outgoingMessage = [ThreadUtil sendMessageWithText:messageText
messageSender:self.messageSender inThread:self.thread
completion:^(NSError *_Nullable error) { messageSender:self.messageSender
sendCompletion(error, outgoingMessage); success:^{
}]; sendCompletion(nil, outgoingMessage);
} }
}]; failure:^(NSError *_Nonnull error) {
sendCompletion(error, outgoingMessage);
}];
}
- (void)sendAsAttachmentMessage:(SendCompletionBlock)sendCompletion
{
__block TSOutgoingMessage *outgoingMessage = nil;
outgoingMessage = [ThreadUtil sendMessageWithAttachment:self.attachment
inThread:self.thread
messageSender:self.messageSender
completion:^(NSError *_Nullable error) {
sendCompletion(error, outgoingMessage);
}];
} }
- (void)showSendFailureAlertWithError:(NSError *)error - (void)showSendFailureAlertWithError:(NSError *)error

@ -419,9 +419,14 @@ public class SignalAttachment: NSObject {
return dataUTI == kOversizeTextAttachmentUTI return dataUTI == kOversizeTextAttachmentUTI
} }
@objc
public var isText: Bool {
return UTTypeConformsTo(dataUTI as CFString, kUTTypeText) || isOversizeText
}
@objc @objc
public var isUrl: Bool { public var isUrl: Bool {
return dataUTI == (kUTTypeURL as String) return UTTypeConformsTo(dataUTI as CFString, kUTTypeURL)
} }
@objc @objc

@ -117,6 +117,10 @@ CGFloat ScaleFromIPhone5(CGFloat iPhone5Value);
// Add red border to self, and all subviews recursively. // Add red border to self, and all subviews recursively.
- (void)addRedBorderRecursively; - (void)addRedBorderRecursively;
- (void)logFrameLater;
- (void)logFrameLaterWithLabel:(NSString *)label;
- (void)logHierarchyUpwardLaterWithLabel:(NSString *)label;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -496,6 +496,39 @@ CGFloat ScaleFromIPhone5(CGFloat iPhone5Value)
} }
} }
- (void)logFrameLater
{
[self logFrameLaterWithLabel:@""];
}
- (void)logFrameLaterWithLabel:(NSString *)label
{
dispatch_async(dispatch_get_main_queue(), ^{
DDLogVerbose(@"%@ %@ frame: %@, hidden: %d, opacity: %f",
self.logTag,
label,
NSStringFromCGRect(self.frame),
self.hidden,
self.layer.opacity);
});
}
- (void)logHierarchyUpwardLaterWithLabel:(NSString *)label
{
dispatch_async(dispatch_get_main_queue(), ^{
DDLogVerbose(@"%@ %@ ----", self.logTag, label);
});
UIResponder *responder = self;
while (responder) {
if ([responder isKindOfClass:[UIView class]]) {
UIView *view = (UIView *)responder;
[view logFrameLaterWithLabel:@"\t"];
}
responder = responder.nextResponder;
}
}
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

@ -538,17 +538,17 @@ public class ShareViewController: UINavigationController, ShareViewDelegate, SAE
} }
Logger.info("\(self.logTag) attachment: \(itemProvider)") Logger.info("\(self.logTag) attachment: \(itemProvider)")
guard let utiType = ShareViewController.utiTypeForItem(itemProvider: itemProvider) else { guard let srcUtiType = ShareViewController.utiTypeForItem(itemProvider: itemProvider) else {
let error = ShareViewControllerError.unsupportedMedia let error = ShareViewControllerError.unsupportedMedia
return Promise(error: error) return Promise(error: error)
} }
Logger.debug("\(logTag) matched utiType: \(utiType)") Logger.debug("\(logTag) matched utiType: \(srcUtiType)")
let (promise, fulfill, reject) = Promise<URL>.pending() let (promise, fulfill, reject) = Promise<(URL, String)>.pending()
var customFileName: String? var customFileName: String?
itemProvider.loadItem(forTypeIdentifier: utiType, options: nil, completionHandler: { itemProvider.loadItem(forTypeIdentifier: srcUtiType, options: nil, completionHandler: {
(provider, error) in (provider, error) in
guard error == nil else { guard error == nil else {
@ -570,14 +570,14 @@ public class ShareViewController: UINavigationController, ShareViewDelegate, SAE
customFileName = "Contact.vcf" customFileName = "Contact.vcf"
} }
let customFileExtension = MIMETypeUtil.fileExtension(forUTIType:utiType) let customFileExtension = MIMETypeUtil.fileExtension(forUTIType:srcUtiType)
guard let tempFilePath = OWSFileSystem.writeData(toTemporaryFile: data, fileExtension: customFileExtension) else { guard let tempFilePath = OWSFileSystem.writeData(toTemporaryFile: data, fileExtension: customFileExtension) else {
let writeError = ShareViewControllerError.assertionError(description: "Error writing item data: \(String(describing: error))") let writeError = ShareViewControllerError.assertionError(description: "Error writing item data: \(String(describing: error))")
reject(writeError) reject(writeError)
return return
} }
let fileUrl = URL(fileURLWithPath:tempFilePath) let fileUrl = URL(fileURLWithPath:tempFilePath)
fulfill(fileUrl) fulfill((fileUrl, srcUtiType))
} else if let string = provider as? String { } else if let string = provider as? String {
guard let data = string.data(using: String.Encoding.utf8) else { guard let data = string.data(using: String.Encoding.utf8) else {
let writeError = ShareViewControllerError.assertionError(description: "Error writing item data: \(String(describing: error))") let writeError = ShareViewControllerError.assertionError(description: "Error writing item data: \(String(describing: error))")
@ -590,9 +590,13 @@ public class ShareViewController: UINavigationController, ShareViewDelegate, SAE
return return
} }
let fileUrl = URL(fileURLWithPath:tempFilePath) let fileUrl = URL(fileURLWithPath:tempFilePath)
fulfill(fileUrl) if UTTypeConformsTo(srcUtiType as CFString, kUTTypeText) {
fulfill((fileUrl, srcUtiType))
} else {
fulfill((fileUrl, kUTTypeText as String))
}
} else if let url = provider as? URL { } else if let url = provider as? URL {
fulfill(url) fulfill((url, srcUtiType))
} else { } else {
let unexpectedTypeError = ShareViewControllerError.assertionError(description: "unexpected item type: \(String(describing: provider))") let unexpectedTypeError = ShareViewControllerError.assertionError(description: "unexpected item type: \(String(describing: provider))")
reject(unexpectedTypeError) reject(unexpectedTypeError)
@ -602,7 +606,7 @@ public class ShareViewController: UINavigationController, ShareViewDelegate, SAE
// TODO accept other data types // TODO accept other data types
// TODO whitelist attachment types // TODO whitelist attachment types
// TODO coerce when necessary and possible // TODO coerce when necessary and possible
return promise.then { (itemUrl: URL) -> Promise<SignalAttachment> in return promise.then { (itemUrl: URL, utiType: String) -> Promise<SignalAttachment> in
let url: URL = try { let url: URL = try {
if self.isVideoNeedingRelocation(itemProvider: itemProvider, itemUrl: itemUrl) { if self.isVideoNeedingRelocation(itemProvider: itemProvider, itemUrl: itemUrl) {
@ -612,7 +616,7 @@ public class ShareViewController: UINavigationController, ShareViewDelegate, SAE
} }
}() }()
Logger.debug("\(self.logTag) building DataSource with url: \(url)") Logger.debug("\(self.logTag) building DataSource with url: \(url), utiType: \(utiType)")
guard let dataSource = ShareViewController.createDataSource(utiType : utiType, url : url, customFileName : customFileName) else { guard let dataSource = ShareViewController.createDataSource(utiType : utiType, url : url, customFileName : customFileName) else {
throw ShareViewControllerError.assertionError(description: "Unable to read attachment data") throw ShareViewControllerError.assertionError(description: "Unable to read attachment data")

Loading…
Cancel
Save