Skip to content

Commit

Permalink
Add OMC-1016 [Nimbus] "Open Share Sheet" Card Messaging Action (#23094)
Browse files Browse the repository at this point in the history
* nimbus sharesheet action

* nimbus sharesheet action

* nimbus sharesheet action

* nimbus sharesheet action

* nimbus sharesheet action

* nimbus sharesheet action

* Update RouteTests.swift

* Update messaging-evergreen-messages.fml.yaml
  • Loading branch information
halemu authored Nov 15, 2024
1 parent c356362 commit b3c6687
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 5 deletions.
14 changes: 12 additions & 2 deletions firefox-ios/Client/Coordinators/Browser/BrowserCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ class BrowserCoordinator: BaseCoordinator,
}

switch route {
case .searchQuery, .search, .searchURL, .glean, .homepanel, .action, .fxaSignIn, .defaultBrowser:
case .searchQuery, .search, .searchURL, .glean, .homepanel, .action, .fxaSignIn, .defaultBrowser, .sharesheet:
return true
case let .settings(section):
return canHandleSettings(with: section)
Expand All @@ -273,6 +273,9 @@ class BrowserCoordinator: BaseCoordinator,
case let .searchURL(url, tabId):
handle(searchURL: url, tabId: tabId)

case let .sharesheet(url, title):
showShareSheet(with: url, title: title)

case let .glean(url):
glean.handleDeeplinkUrl(url: url)

Expand Down Expand Up @@ -514,11 +517,16 @@ class BrowserCoordinator: BaseCoordinator,
}

func showShareSheet(with url: URL?) {
showShareSheet(with: url, title: nil)
}

func showShareSheet(with url: URL?, title: String?) {
guard let url else { return }

let showShareSheet = { url in
self.showShareExtension(
url: url,
title: title,
sourceView: self.browserViewController.addressToolbarContainer,
toastContainer: self.browserViewController.contentContainer,
popoverArrowDirection: .any
Expand Down Expand Up @@ -692,6 +700,7 @@ class BrowserCoordinator: BaseCoordinator,

func showShareExtension(
url: URL,
title: String?,
sourceView: UIView,
sourceRect: CGRect?,
toastContainer: UIView,
Expand All @@ -713,6 +722,7 @@ class BrowserCoordinator: BaseCoordinator,
add(child: shareExtensionCoordinator)
shareExtensionCoordinator.start(
url: url,
title: title,
sourceView: sourceView,
sourceRect: sourceRect,
popoverArrowDirection: popoverArrowDirection
Expand Down Expand Up @@ -897,7 +907,7 @@ class BrowserCoordinator: BaseCoordinator,
router.present(viewController)
}

// MARK: - Password Generator
// MARK: - Password Generator
func showPasswordGenerator(tab: Tab, frame: WKFrameInfo) {
let passwordGenVC = PasswordGeneratorViewController(windowUUID: windowUUID, currentTab: tab, currentFrame: frame)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ protocol BrowserNavigationHandler: AnyObject, QRCodeNavigationHandler {
/// from actions in the share extension
/// - Parameter popoverArrowDirection: The arrow direction for the view controller presented as popover.
func showShareExtension(url: URL,
title: String?,
sourceView: UIView,
sourceRect: CGRect?,
toastContainer: UIView,
Expand Down Expand Up @@ -108,13 +109,15 @@ protocol BrowserNavigationHandler: AnyObject, QRCodeNavigationHandler {
extension BrowserNavigationHandler {
func showShareExtension(
url: URL,
title: String? = nil,
sourceView: UIView,
sourceRect: CGRect? = nil,
toastContainer: UIView,
popoverArrowDirection: UIPopoverArrowDirection = .up
) {
showShareExtension(
url: url,
title: title,
sourceView: sourceView,
sourceRect: sourceRect,
toastContainer: toastContainer,
Expand Down
1 change: 1 addition & 0 deletions firefox-ios/Client/Coordinators/Router/DeeplinkInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ enum DeeplinkInput {
case fxaSignIn = "fxa-signin"
case openUrl = "open-url"
case openText = "open-text"
case sharesheet = "share-sheet"
case glean
case widgetMediumTopSitesOpenUrl = "widget-medium-topsites-open-url"
case widgetSmallQuickLinkOpenUrl = "widget-small-quicklink-open-url"
Expand Down
7 changes: 7 additions & 0 deletions firefox-ios/Client/Coordinators/Router/Route.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ enum Route: Equatable {
/// settings to be displayed.
case defaultBrowser(section: DefaultBrowserSection)

/// A route for opening a share sheet with a URL and an optional message.
///
/// - Parameters:
/// - url: The `URL` object to be shared from the share sheet.
/// - title: An optional string to be used as the message in the share sheet.
case sharesheet(url: URL, title: String?)

/// An enumeration representing different sections of the home panel.
enum HomepanelSection: String, CaseIterable, Equatable {
case bookmarks
Expand Down
11 changes: 10 additions & 1 deletion firefox-ios/Client/Coordinators/Router/RouteBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ final class RouteBuilder {

case .fxaSignIn:
return nil

case .sharesheet:
let linkString = urlScanner.value(query: "url")
let titleText = urlScanner.value(query: "title")
if let link = linkString, let url = URL(string: link) {
return .sharesheet(url: url, title: titleText)
} else {
return nil
}
}
} else if urlScanner.isHTTPScheme {
TelemetryWrapper.gleanRecordEvent(category: .action, method: .open, object: .asDefaultBrowser)
Expand Down Expand Up @@ -192,7 +201,7 @@ final class RouteBuilder {

private func recordTelemetry(input: DeeplinkInput.Host, isPrivate: Bool) {
switch input {
case .deepLink, .fxaSignIn, .glean:
case .deepLink, .fxaSignIn, .glean, .sharesheet:
return
case .widgetMediumTopSitesOpenUrl:
TelemetryWrapper.recordEvent(category: .action, method: .open, object: .mediumTopSitesWidget)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,15 @@ class ShareExtensionCoordinator: BaseCoordinator,
/// Presents the Share extension from the source view
func start(
url: URL,
title: String? = nil,
sourceView: UIView,
sourceRect: CGRect? = nil,
popoverArrowDirection: UIPopoverArrowDirection = .up
) {
let shareExtension = ShareExtensionHelper(url: url, tab: tabManager.selectedTab)
let shareExtension = ShareExtensionHelper(
url: url,
title: title ?? tabManager.selectedTab?.title,
tab: tabManager.selectedTab)
let controller = shareExtension.createActivityViewController(
tabManager.selectedTab?.webView
) { [weak self] completed, activityType in
Expand Down
10 changes: 9 additions & 1 deletion firefox-ios/Client/Frontend/Share/ShareExtensionHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class ShareExtensionHelper: NSObject, FeatureFlaggable {
private weak var selectedTab: Tab?

private let url: URL
private let title: String?
private var onePasswordExtensionItem: NSExtensionItem!
private let browserFillIdentifier = "org.appextension.fill-browser-action"
private let pocketIconExtension = "com.ideashower.ReadItLaterPro.AddToPocketExtension"
Expand All @@ -22,8 +23,9 @@ class ShareExtensionHelper: NSObject, FeatureFlaggable {
}

// Can be a file:// or http(s):// url
init(url: URL, tab: Tab?) {
init(url: URL, title: String? = nil, tab: Tab?) {
self.url = url
self.title = title
self.selectedTab = tab
}

Expand Down Expand Up @@ -83,6 +85,12 @@ class ShareExtensionHelper: NSObject, FeatureFlaggable {
guard !url.isFileURL else { return [url] }

var activityItems = [Any]()

// Add the title (if it exists)
if let title = self.title {
activityItems.append(title)
}

let printInfo = UIPrintInfo(dictionary: nil)
printInfo.jobName = (url.absoluteString as NSString).lastPathComponent
printInfo.outputType = .general
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,24 @@ final class BrowserCoordinatorTests: XCTestCase, FeatureFlaggable {
XCTAssertTrue(mockRouter.presentedViewController is UIActivityViewController)
}

func testShowShareExtension_addsShareExtensionCoordinatorWithTitle() {
let subject = createSubject()

subject.showShareExtension(
url: URL(
string: "https://www.google.com"
)!,
title: "TEST TITLE",
sourceView: UIView(),
toastContainer: UIView()
)

XCTAssertEqual(subject.childCoordinators.count, 1)
XCTAssertTrue(subject.childCoordinators.first is ShareExtensionCoordinator)
XCTAssertEqual(mockRouter.presentCalled, 1)
XCTAssertTrue(mockRouter.presentedViewController is UIActivityViewController)
}

func testShowCreditCardAutofill_addsCredentialAutofillCoordinator() {
let subject = createSubject()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,24 @@ class RouteTests: XCTestCase {
XCTAssertEqual(route, .searchQuery(query: "google", isPrivate: false))
}

func testShareSheetRouteUrlOnly() {
let subject = createSubject()
let url = URL(string: "firefox://share-sheet?url=https://www.google.com")!

let route = subject.makeRoute(url: url)

XCTAssertEqual(route, .sharesheet(url: URL(string: "https://www.google.com")!, title: nil))
}

func testShareSheetRouteUrlAndTitle() {
let subject = createSubject()
let url = URL(string: "firefox://share-sheet?url=https://www.google.com&title=TEST TITLE")!

let route = subject.makeRoute(url: url)

XCTAssertEqual(route, .sharesheet(url: URL(string: "https://www.google.com")!, title: "TEST TITLE"))
}

// MARK: - AppAction

func testAppAction_showIntroOnboarding() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import:
OPEN_NEW_TAB: ://deep-link?url=homepanel/new-tab
MAKE_DEFAULT_BROWSER: ://deep-link?url=default-browser/system-settings
MAKE_DEFAULT_BROWSER_WITH_TUTORIAL: ://deep-link?url=default-browser/tutorial
OPEN_SHARE_SHEET: ://share-sheet
styles:
FALLBACK:
priority: 40
Expand Down

0 comments on commit b3c6687

Please sign in to comment.