From b767803685a0c528a75e7bd622b9a3da5f60a7f0 Mon Sep 17 00:00:00 2001 From: Nate Heagy Date: Thu, 14 Mar 2019 15:32:51 -0700 Subject: [PATCH 1/7] Add first pass at opening a shared file - this is horrible. fix it before merging. --- .../ShareExtractor.swift | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/WordPress/WordPressShareExtension/ShareExtractor.swift b/WordPress/WordPressShareExtension/ShareExtractor.swift index 5e69725ba3d9..b8c19b3ee321 100644 --- a/WordPress/WordPressShareExtension/ShareExtractor.swift +++ b/WordPress/WordPressShareExtension/ShareExtractor.swift @@ -144,21 +144,21 @@ private extension ShareExtractor { return } textExtractor.extract(context: extensionContext) { extractedItems in - guard extractedItems.count > 0 else { + guard extractedItems.count > 0 else { completion(nil) - return + return + } + let combinedTitle = extractedItems.compactMap({ $0.title }).joined(separator: " ") + let combinedDescription = extractedItems.compactMap({ $0.description }).joined(separator: " ") + let combinedSelectedText = extractedItems.compactMap({ $0.selectedText }).joined(separator: "\n\n") + let urls = extractedItems.compactMap({ $0.url }) + + completion(ExtractedItem(selectedText: combinedSelectedText, + description: combinedDescription, + url: urls.first, + title: combinedTitle, + image: nil)) } - let combinedTitle = extractedItems.compactMap({ $0.title }).joined(separator: " ") - let combinedDescription = extractedItems.compactMap({ $0.description }).joined(separator: " ") - let combinedSelectedText = extractedItems.compactMap({ $0.selectedText }).joined(separator: "\n\n") - let urls = extractedItems.compactMap({ $0.url }) - - completion(ExtractedItem(selectedText: combinedSelectedText, - description: combinedDescription, - url: urls.first, - title: combinedTitle, - image: nil)) - } } func extractImages(completion: @escaping ([UIImage]?) -> Void) { @@ -195,6 +195,7 @@ private extension TypeBasedExtensionContentExtractor { func extract(context: NSExtensionContext, completion: @escaping ([ExtractedItem]) -> Void) { let itemProviders = context.itemProviders(ofType: acceptedType) + print(acceptedType) var results = [ExtractedItem]() guard itemProviders.count > 0 else { DispatchQueue.main.async { @@ -230,13 +231,24 @@ private struct URLExtractor: TypeBasedExtensionContentExtractor { let acceptedType = kUTTypeURL as String func convert(payload: URL) -> ExtractedItem? { - guard !payload.isFileURL else { - return nil - } +// guard !payload.isFileURL else { +// let contents = try? String(contentsOf: payload) +// return ExtractedItem(selectedText: contents, description: nil, url: nil, title: nil, image: nil) +// } var returnedItem = ExtractedItem() returnedItem.url = payload + + if payload.isFileURL { + let html = try? String(contentsOf: payload) ?? "" + returnedItem.selectedText = html?.escapeHtmlNamedEntities() + } + return returnedItem } + + private func extractBodyContents(html: String) { + let bodyParts = html.components(separatedBy: " Date: Fri, 15 Mar 2019 09:35:54 -0700 Subject: [PATCH 2/7] Add initial support for plain text file importing --- .../ShareExtractor.swift | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/WordPress/WordPressShareExtension/ShareExtractor.swift b/WordPress/WordPressShareExtension/ShareExtractor.swift index b8c19b3ee321..c1d05652154a 100644 --- a/WordPress/WordPressShareExtension/ShareExtractor.swift +++ b/WordPress/WordPressShareExtension/ShareExtractor.swift @@ -231,23 +231,30 @@ private struct URLExtractor: TypeBasedExtensionContentExtractor { let acceptedType = kUTTypeURL as String func convert(payload: URL) -> ExtractedItem? { -// guard !payload.isFileURL else { -// let contents = try? String(contentsOf: payload) -// return ExtractedItem(selectedText: contents, description: nil, url: nil, title: nil, image: nil) -// } + guard !payload.isFileURL else { + return processLocalFile(url: payload) + } + var returnedItem = ExtractedItem() returnedItem.url = payload - if payload.isFileURL { - let html = try? String(contentsOf: payload) ?? "" - returnedItem.selectedText = html?.escapeHtmlNamedEntities() + return returnedItem } - return returnedItem + private func processLocalFile(url: URL) -> ExtractedItem? { + switch url.pathExtension { + case "text", "txt": + return handlePlainTextFile(url: url) + default: + return nil + } } - private func extractBodyContents(html: String) { - let bodyParts = html.components(separatedBy: " ExtractedItem? { + var returnedItem = ExtractedItem() + let html = (try? String(contentsOf: url)) ?? "" + returnedItem.selectedText = html.escapeHtmlNamedEntities() + return returnedItem } } From 6bd0652261988b6c9d68f0146fa8119d1bef2b84 Mon Sep 17 00:00:00 2001 From: Nate Heagy Date: Fri, 15 Mar 2019 09:51:31 -0700 Subject: [PATCH 3/7] Give imported text unquoted appearance --- .../ShareExtractor.swift | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/WordPress/WordPressShareExtension/ShareExtractor.swift b/WordPress/WordPressShareExtension/ShareExtractor.swift index c1d05652154a..369fdcc5c018 100644 --- a/WordPress/WordPressShareExtension/ShareExtractor.swift +++ b/WordPress/WordPressShareExtension/ShareExtractor.swift @@ -9,11 +9,10 @@ struct ExtractedShare { var description: String var url: URL? var selectedText: String + var importedText: String var images: [UIImage] var combinedContentHTML: String { - var returnString: String - var rawLink = "" var readOnText = "" @@ -25,23 +24,26 @@ struct ExtractedShare { } // Build the returned string by doing the following: - // * 1st check: Look for selected text, if it exists put it into a blockquote. - // * 2nd check: No selected text, but we have a page description...use that. - // * 3rd check: No selected text, but we have a page title...use that. + // * 1: Look for imported text. + // * 2: Look for selected text, if it exists put it into a blockquote. + // * 3: No selected text, but we have a page description...use that. + // * 4: No selected text, but we have a page title...use that. // * Finally, default to a simple link if nothing else is found - if selectedText.isEmpty { - if !description.isEmpty { - returnString = "

\(description)\(readOnText)

" - } else if !title.isEmpty { - returnString = "

\(title)\(readOnText)

" - } else { - returnString = "

\(rawLink)

" - } - } else { - returnString = "

\(selectedText)\(readOnText)

" + guard importedText.isEmpty else { + return "

\(importedText.escapeHtmlNamedEntities())

" } - return returnString + guard selectedText.isEmpty else { + return "

\(selectedText)\(readOnText)

" + } + + if !description.isEmpty { + return "

\(description)\(readOnText)

" + } else if !title.isEmpty { + return "

\(title)\(readOnText)

" + } else { + return "

\(rawLink)

" + } } } @@ -66,6 +68,7 @@ struct ShareExtractor { let title = extractedTextResults?.title ?? "" let description = extractedTextResults?.description ?? "" let selectedText = extractedTextResults?.selectedText ?? "" + let importedText = extractedTextResults?.importedText ?? "" let url = extractedTextResults?.url let returnedImages = images ?? [UIImage]() @@ -73,6 +76,7 @@ struct ShareExtractor { description: description, url: url, selectedText: selectedText, + importedText: importedText, images: returnedImages)) } } @@ -100,6 +104,10 @@ private struct ExtractedItem { /// var selectedText: String? + /// Text that was imported from another app + /// + var importedText: String? + /// A description of the resource if available /// var description: String? @@ -151,9 +159,11 @@ private extension ShareExtractor { let combinedTitle = extractedItems.compactMap({ $0.title }).joined(separator: " ") let combinedDescription = extractedItems.compactMap({ $0.description }).joined(separator: " ") let combinedSelectedText = extractedItems.compactMap({ $0.selectedText }).joined(separator: "\n\n") + let combinedImportedText = extractedItems.compactMap({ $0.importedText }).joined(separator: "\n\n") let urls = extractedItems.compactMap({ $0.url }) completion(ExtractedItem(selectedText: combinedSelectedText, + importedText: combinedImportedText, description: combinedDescription, url: urls.first, title: combinedTitle, @@ -239,7 +249,7 @@ private struct URLExtractor: TypeBasedExtensionContentExtractor { returnedItem.url = payload return returnedItem - } + } private func processLocalFile(url: URL) -> ExtractedItem? { switch url.pathExtension { @@ -252,8 +262,8 @@ private struct URLExtractor: TypeBasedExtensionContentExtractor { private func handlePlainTextFile(url: URL) -> ExtractedItem? { var returnedItem = ExtractedItem() - let html = (try? String(contentsOf: url)) ?? "" - returnedItem.selectedText = html.escapeHtmlNamedEntities() + let rawText = (try? String(contentsOf: url)) ?? "" + returnedItem.importedText = rawText return returnedItem } } From 54b0ff721699d1a7b3e464d96159c93de120b7f8 Mon Sep 17 00:00:00 2001 From: Nate Heagy Date: Fri, 15 Mar 2019 09:52:27 -0700 Subject: [PATCH 4/7] Stop imported text selection from carrying HTML --- WordPress/WordPressShareExtension/ShareExtractor.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/WordPressShareExtension/ShareExtractor.swift b/WordPress/WordPressShareExtension/ShareExtractor.swift index 369fdcc5c018..15a61aca052b 100644 --- a/WordPress/WordPressShareExtension/ShareExtractor.swift +++ b/WordPress/WordPressShareExtension/ShareExtractor.swift @@ -34,7 +34,7 @@ struct ExtractedShare { } guard selectedText.isEmpty else { - return "

\(selectedText)\(readOnText)

" + return "

\(selectedText.escapeHtmlNamedEntities())\(readOnText)

" } if !description.isEmpty { From b9d8bd4006c374974ce323e536de412c959852fc Mon Sep 17 00:00:00 2001 From: Nate Heagy Date: Fri, 15 Mar 2019 11:09:16 -0700 Subject: [PATCH 5/7] Fix some weird indenting in ShareExtractor.swift --- .../ShareExtractor.swift | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/WordPress/WordPressShareExtension/ShareExtractor.swift b/WordPress/WordPressShareExtension/ShareExtractor.swift index 15a61aca052b..9a59f4ca67f2 100644 --- a/WordPress/WordPressShareExtension/ShareExtractor.swift +++ b/WordPress/WordPressShareExtension/ShareExtractor.swift @@ -152,23 +152,23 @@ private extension ShareExtractor { return } textExtractor.extract(context: extensionContext) { extractedItems in - guard extractedItems.count > 0 else { + guard extractedItems.count > 0 else { completion(nil) - return - } - let combinedTitle = extractedItems.compactMap({ $0.title }).joined(separator: " ") - let combinedDescription = extractedItems.compactMap({ $0.description }).joined(separator: " ") - let combinedSelectedText = extractedItems.compactMap({ $0.selectedText }).joined(separator: "\n\n") - let combinedImportedText = extractedItems.compactMap({ $0.importedText }).joined(separator: "\n\n") - let urls = extractedItems.compactMap({ $0.url }) - - completion(ExtractedItem(selectedText: combinedSelectedText, - importedText: combinedImportedText, - description: combinedDescription, - url: urls.first, - title: combinedTitle, - image: nil)) + return } + let combinedTitle = extractedItems.compactMap({ $0.title }).joined(separator: " ") + let combinedDescription = extractedItems.compactMap({ $0.description }).joined(separator: " ") + let combinedSelectedText = extractedItems.compactMap({ $0.selectedText }).joined(separator: "\n\n") + let combinedImportedText = extractedItems.compactMap({ $0.importedText }).joined(separator: "\n\n") + let urls = extractedItems.compactMap({ $0.url }) + + completion(ExtractedItem(selectedText: combinedSelectedText, + importedText: combinedImportedText, + description: combinedDescription, + url: urls.first, + title: combinedTitle, + image: nil)) + } } func extractImages(completion: @escaping ([UIImage]?) -> Void) { From 174b3062d410ec302a27149e9c47203c689968bf Mon Sep 17 00:00:00 2001 From: Nate Heagy Date: Fri, 15 Mar 2019 11:10:38 -0700 Subject: [PATCH 6/7] Added release note for improved text import --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 49fc836b1198..18ca35ac7d53 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,6 +1,7 @@ 12.1 ----- * Improve messages when updates to user account details fail because of server logic, for exanple email being used for another account. +* Improved text import from other apps, such as Bear or Ulysses 🥰 12.0 ----- From 4e3cc2e7e9d44ff8e7f0de14e3bf1c7cafc0520b Mon Sep 17 00:00:00 2001 From: Nate Heagy Date: Fri, 15 Mar 2019 23:06:39 -0700 Subject: [PATCH 7/7] cleanup ShareExtractor.swift --- WordPress/WordPressShareExtension/ShareExtractor.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WordPress/WordPressShareExtension/ShareExtractor.swift b/WordPress/WordPressShareExtension/ShareExtractor.swift index 9a59f4ca67f2..5706862d4d32 100644 --- a/WordPress/WordPressShareExtension/ShareExtractor.swift +++ b/WordPress/WordPressShareExtension/ShareExtractor.swift @@ -30,7 +30,7 @@ struct ExtractedShare { // * 4: No selected text, but we have a page title...use that. // * Finally, default to a simple link if nothing else is found guard importedText.isEmpty else { - return "

\(importedText.escapeHtmlNamedEntities())

" + return importedText.escapeHtmlNamedEntities() } guard selectedText.isEmpty else { @@ -205,7 +205,6 @@ private extension TypeBasedExtensionContentExtractor { func extract(context: NSExtensionContext, completion: @escaping ([ExtractedItem]) -> Void) { let itemProviders = context.itemProviders(ofType: acceptedType) - print(acceptedType) var results = [ExtractedItem]() guard itemProviders.count > 0 else { DispatchQueue.main.async {