Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Fix #8070: Support 'Clean Copy Link' from Sharesheet (#8626)
Browse files Browse the repository at this point in the history
  • Loading branch information
soner-yuksel authored Jan 5, 2024
1 parent 6fbee77 commit 57095b8
Show file tree
Hide file tree
Showing 11 changed files with 333 additions and 588 deletions.
237 changes: 1 addition & 236 deletions Sources/Brave/Frontend/Browser/BrowserViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import CoreData
import StoreKit
import BraveUI
import NetworkExtension
import FeedKit
import SwiftUI
import class Combine.AnyCancellable
import BraveWallet
Expand Down Expand Up @@ -1217,7 +1216,7 @@ public class BrowserViewController: UIViewController {
/// Whether or not to show the playlist onboarding callout this session
var shouldShowPlaylistOnboardingThisSession = true

fileprivate func showQueuedAlertIfAvailable() {
public func showQueuedAlertIfAvailable() {
if let queuedAlertInfo = tabManager.selectedTab?.dequeueJavascriptAlertPrompt() {
let alertController = queuedAlertInfo.alertController()
alertController.delegate = self
Expand Down Expand Up @@ -2117,240 +2116,6 @@ public class BrowserViewController: UIViewController {
topToolbar.didClickCancel()
}
}

func makeShareActivities(for url: URL, tab: Tab?, sourceView: UIView?, sourceRect: CGRect, arrowDirection: UIPopoverArrowDirection) -> [UIActivity] {
var activities = [UIActivity]()

// Adding SendTabToSelfActivity conditionally to show device selection screen
if !privateBrowsingManager.isPrivateBrowsing, !url.isLocal, !InternalURL.isValid(url: url), !url.isReaderModeURL,
braveCore.syncAPI.isSendTabToSelfVisible {
let sendTabToSelfActivity = SendTabToSelfActivity() { [weak self] in
guard let self = self else { return }

let deviceList = self.braveCore.sendTabAPI.getListOfSyncedDevices()
let dataSource = SendableTabInfoDataSource(
with: deviceList,
displayTitle: tab?.displayTitle ?? "",
sendableURL: url)

let controller = SendTabToSelfController(sendTabAPI: self.braveCore.sendTabAPI, dataSource: dataSource)

controller.sendWebSiteHandler = { [weak self] dataSource in
guard let self = self else { return }

self.present(
SendTabProcessController(type: .progress, data: dataSource, sendTabAPI: self.braveCore.sendTabAPI),
animated: true,
completion: nil)
}
self.present(controller, animated: true, completion: nil)
}

activities.append(sendTabToSelfActivity)
}

if let tab = self.tabManager.selectedTab, tab.secureContentState.shouldDisplayWarning {
if tab.readerModeAvailableOrActive {
// If the reader mode button is occluded due to a secure content state warning add it as an activity
activities.append(
BasicMenuActivity(
title: Strings.toggleReaderMode,
braveSystemImage: "leo.product.speedreader",
callback: { [weak self] in
self?.toggleReaderMode()
}
)
)
}
// Any other buttons on the leading side of the location view should be added here as well
}

let findInPageActivity = FindInPageActivity() { [unowned self] in
if #available(iOS 16.0, *), let findInteraction = self.tabManager.selectedTab?.webView?.findInteraction {
findInteraction.searchText = ""
findInteraction.presentFindNavigator(showingReplace: false)
} else {
self.updateFindInPageVisibility(visible: true)
}
}

let pageZoomActivity = PageZoomActivity() { [unowned self] in
self.displayPageZoom(visible: true)
}

activities.append(contentsOf: [findInPageActivity, pageZoomActivity])

// These actions don't apply if we're sharing a temporary document
if !url.isFileURL {
// We don't allow to have 2 same favorites.
if !FavoritesHelper.isAlreadyAdded(url) {
activities.append(
AddToFavoritesActivity() { [weak self, weak tab] in
guard let self = self else { return }

FavoritesHelper.add(url: url, title: tab?.displayTitle)
// Handle App Rating
// Check for review condition after adding a favorite
AppReviewManager.shared.handleAppReview(for: .revised, using: self)
})
}

activities.append(
RequestDesktopSiteActivity(tab: tab) { [weak tab] in
tab?.switchUserAgent()
})

if Preferences.BraveNews.isEnabled.value, let metadata = tab?.pageMetadata,
!metadata.feeds.isEmpty {
let feeds: [RSSFeedLocation] = metadata.feeds.compactMap { feed in
guard let url = URL(string: feed.href) else { return nil }
return RSSFeedLocation(title: feed.title, url: url)
}
if !feeds.isEmpty {
let addToBraveNews = AddFeedToBraveNewsActivity() { [weak self] in
guard let self = self else { return }
let controller = BraveNewsAddSourceResultsViewController(
dataSource: self.feedDataSource,
searchedURL: url,
rssFeedLocations: feeds,
sourcesAdded: nil
)
let container = UINavigationController(rootViewController: controller)
let idiom = UIDevice.current.userInterfaceIdiom
container.modalPresentationStyle = idiom == .phone ? .pageSheet : .formSheet
self.present(container, animated: true)
}
activities.append(addToBraveNews)
}
}

if let webView = tab?.webView, tab?.temporaryDocument == nil {
let createPDFActivity = CreatePDFActivity() {
webView.createPDF { [weak self] result in
dispatchPrecondition(condition: .onQueue(.main))
guard let self = self else {
return
}
switch result {
case .success(let pdfData):
// Create a valid filename
let validFilenameSet = CharacterSet(charactersIn: ":/")
.union(.newlines)
.union(.controlCharacters)
.union(.illegalCharacters)
let filename = webView.title?.components(separatedBy: validFilenameSet).joined()
let url = URL(fileURLWithPath: NSTemporaryDirectory())
.appendingPathComponent("\(filename ?? "Untitled").pdf")
do {
try pdfData.write(to: url)
let pdfActivityController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
if let popoverPresentationController = pdfActivityController.popoverPresentationController {
popoverPresentationController.sourceView = sourceView
popoverPresentationController.sourceRect = sourceRect
popoverPresentationController.permittedArrowDirections = arrowDirection
popoverPresentationController.delegate = self
}
self.present(pdfActivityController, animated: true)
} catch {
Logger.module.error("Failed to write PDF to disk: \(error.localizedDescription, privacy: .public)")
}

case .failure(let error):
Logger.module.error("Failed to create PDF with error: \(error.localizedDescription)")
}
}
}
activities.append(createPDFActivity)
}

} else {
// Check if it's a feed, url is a temp document file URL
if let selectedTab = tabManager.selectedTab,
(selectedTab.mimeType == "application/xml" || selectedTab.mimeType == "application/json"),
let tabURL = selectedTab.url {

let parser = FeedParser(URL: url)
if case .success(let feed) = parser.parse() {
let addToBraveNews = AddFeedToBraveNewsActivity() { [weak self] in
guard let self = self else { return }
let controller = BraveNewsAddSourceResultsViewController(
dataSource: self.feedDataSource,
searchedURL: tabURL,
rssFeedLocations: [.init(title: feed.title, url: tabURL)],
sourcesAdded: nil
)
let container = UINavigationController(rootViewController: controller)
let idiom = UIDevice.current.userInterfaceIdiom
container.modalPresentationStyle = idiom == .phone ? .pageSheet : .formSheet
self.present(container, animated: true)
}
activities.append(addToBraveNews)
}
}
}

if let webView = tabManager.selectedTab?.webView,
evaluateWebsiteSupportOpenSearchEngine(webView) {
let addSearchEngineActivity = AddSearchEngineActivity() { [weak self] in
self?.addCustomSearchEngineForFocusedElement()
}

activities.append(addSearchEngineActivity)
}

if let secureState = tabManager.selectedTab?.secureContentState, secureState != .missingSSL && secureState != .unknown {
let displayCertificateActivity = BasicMenuActivity(title: Strings.displayCertificate, braveSystemImage: "leo.lock.plain") { [weak self] in
self?.displayPageCertificateInfo()
}
activities.append(displayCertificateActivity)
}

activities.append(ReportWebCompatibilityIssueActivity() { [weak self] in
self?.showSubmitReportView(for: url)
})

return activities
}

func presentActivityViewController(_ url: URL, tab: Tab? = nil, sourceView: UIView?, sourceRect: CGRect, arrowDirection: UIPopoverArrowDirection) {
let activities: [UIActivity] = makeShareActivities(
for: url,
tab: tab,
sourceView: sourceView,
sourceRect: sourceRect,
arrowDirection: arrowDirection
)

let controller = ShareExtensionHelper.makeActivityViewController(
selectedURL: url,
selectedTab: tab,
applicationActivities: activities
)

controller.completionWithItemsHandler = { [weak self] _, _, _, _ in
self?.cleanUpCreateActivity()
}

if let popoverPresentationController = controller.popoverPresentationController {
popoverPresentationController.sourceView = sourceView
popoverPresentationController.sourceRect = sourceRect
popoverPresentationController.permittedArrowDirections = arrowDirection
popoverPresentationController.delegate = self
}

present(controller, animated: true, completion: nil)
}

private func cleanUpCreateActivity() {
// After dismissing, check to see if there were any prompts we queued up
showQueuedAlertIfAvailable()

// Usually the popover delegate would handle nil'ing out the references we have to it
// on the BVC when displaying as a popover but the delegate method doesn't seem to be
// invoked on iOS 10. See Bug 1297768 for additional details.
displayedPopoverController = nil
updateDisplayedPopoverProperties = nil
}

func displayPageZoom(visible: Bool) {
if !visible || pageZoomBar != nil {
Expand Down
Loading

0 comments on commit 57095b8

Please sign in to comment.