Skip to content

Commit

Permalink
Add FXIOS-10613 [Homepage] [ContextMenu] Navigation actions (#23971)
Browse files Browse the repository at this point in the history
  • Loading branch information
cyndichin authored Dec 31, 2024
1 parent 6586187 commit 4eabc8c
Show file tree
Hide file tree
Showing 20 changed files with 498 additions and 87 deletions.
18 changes: 17 additions & 1 deletion firefox-ios/Client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,7 @@
8A093D7F2A4B3E7D0099ABA5 /* GeneralSettingsDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A093D7E2A4B3E7D0099ABA5 /* GeneralSettingsDelegate.swift */; };
8A093D812A4B58330099ABA5 /* MockSettingsFlowDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A093D802A4B58330099ABA5 /* MockSettingsFlowDelegate.swift */; };
8A093D832A4B68940099ABA5 /* PrivacySettingsDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A093D822A4B68940099ABA5 /* PrivacySettingsDelegate.swift */; };
8A09BCC32D22F1BE00CFDF60 /* ContextMenuCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A09BCC22D22F1BE00CFDF60 /* ContextMenuCoordinatorTests.swift */; };
8A0A1BA02B2200FD00E8706F /* PrivateHomepageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A0A1B9F2B2200FD00E8706F /* PrivateHomepageViewController.swift */; };
8A0A1BA32B22030100E8706F /* PrivateMessageCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A0A1BA22B22030100E8706F /* PrivateMessageCardCell.swift */; };
8A0D32842A61E1CC007D976D /* StatusBarOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A0D32832A61E1CC007D976D /* StatusBarOverlay.swift */; };
Expand Down Expand Up @@ -906,6 +907,7 @@
8A83B74A2A265044002FF9AC /* SettingsCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A83B7492A265044002FF9AC /* SettingsCoordinatorTests.swift */; };
8A83B74C2A265061002FF9AC /* LibraryCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A83B74B2A265061002FF9AC /* LibraryCoordinatorTests.swift */; };
8A8482F02BE1602500F9007B /* MicrosurveyPromptStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8482EE2BE15FFE00F9007B /* MicrosurveyPromptStateTests.swift */; };
8A855C032D1EE9EF00C1A2F3 /* ContextMenuCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A855C022D1EE9EF00C1A2F3 /* ContextMenuCoordinator.swift */; };
8A8629E2288096C40096DDB1 /* BookmarksFolderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8629E1288096C40096DDB1 /* BookmarksFolderCell.swift */; };
8A8629E72880B7330096DDB1 /* LegacyBookmarksPanelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8629E52880B69C0096DDB1 /* LegacyBookmarksPanelTests.swift */; };
8A86DAD8277298DE00D7BFFF /* ClosedTabsStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A86DAD7277298DE00D7BFFF /* ClosedTabsStoreTests.swift */; };
Expand Down Expand Up @@ -7517,6 +7519,7 @@
8A093D7E2A4B3E7D0099ABA5 /* GeneralSettingsDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsDelegate.swift; sourceTree = "<group>"; };
8A093D802A4B58330099ABA5 /* MockSettingsFlowDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockSettingsFlowDelegate.swift; sourceTree = "<group>"; };
8A093D822A4B68940099ABA5 /* PrivacySettingsDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacySettingsDelegate.swift; sourceTree = "<group>"; };
8A09BCC22D22F1BE00CFDF60 /* ContextMenuCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuCoordinatorTests.swift; sourceTree = "<group>"; };
8A0A1B9F2B2200FD00E8706F /* PrivateHomepageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateHomepageViewController.swift; sourceTree = "<group>"; };
8A0A1BA22B22030100E8706F /* PrivateMessageCardCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateMessageCardCell.swift; sourceTree = "<group>"; };
8A0D32832A61E1CC007D976D /* StatusBarOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBarOverlay.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -7705,6 +7708,7 @@
8A83B7492A265044002FF9AC /* SettingsCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCoordinatorTests.swift; sourceTree = "<group>"; };
8A83B74B2A265061002FF9AC /* LibraryCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryCoordinatorTests.swift; sourceTree = "<group>"; };
8A8482EE2BE15FFE00F9007B /* MicrosurveyPromptStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MicrosurveyPromptStateTests.swift; sourceTree = "<group>"; };
8A855C022D1EE9EF00C1A2F3 /* ContextMenuCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuCoordinator.swift; sourceTree = "<group>"; };
8A8629E1288096C40096DDB1 /* BookmarksFolderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksFolderCell.swift; sourceTree = "<group>"; };
8A8629E52880B69C0096DDB1 /* LegacyBookmarksPanelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyBookmarksPanelTests.swift; sourceTree = "<group>"; };
8A86DAD7277298DE00D7BFFF /* ClosedTabsStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedTabsStoreTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -11387,8 +11391,8 @@
8A00BD852CAB3FC200680AF9 /* Homepage Rebuild */ = {
isa = PBXGroup;
children = (
8A09BCC12D22F1A500CFDF60 /* ContextMenu */,
8AD3AFC42D143F0D00CFC887 /* TopSitesDimensionImplementationTests.swift */,
8A4B66412D1DC962008C5B64 /* ContextMenuConfigurationTests.swift */,
8A87B4352CC1A8FD003A9239 /* Mock */,
8A87B4302CC1A3BA003A9239 /* PocketManagerTests.swift */,
8A552AC22CB43A7000564C98 /* Redux */,
Expand All @@ -11410,6 +11414,15 @@
path = Cell;
sourceTree = "<group>";
};
8A09BCC12D22F1A500CFDF60 /* ContextMenu */ = {
isa = PBXGroup;
children = (
8A4B66412D1DC962008C5B64 /* ContextMenuConfigurationTests.swift */,
8A09BCC22D22F1BE00CFDF60 /* ContextMenuCoordinatorTests.swift */,
);
path = ContextMenu;
sourceTree = "<group>";
};
8A0A1BA12B22010200E8706F /* PrivateHome */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -11754,6 +11767,7 @@
children = (
8AC0B1BF2D1D9356004237FD /* ContextMenuConfiguration.swift */,
8A62B15C2CED408B0045F46E /* ContextMenuState.swift */,
8A855C022D1EE9EF00C1A2F3 /* ContextMenuCoordinator.swift */,
);
path = ContextMenu;
sourceTree = "<group>";
Expand Down Expand Up @@ -16292,6 +16306,7 @@
8AD40FCF27BADC6B00672675 /* URLTextField.swift in Sources */,
31ADB5DA1E58CEC300E87909 /* ClipboardBarDisplayHandler.swift in Sources */,
8AD1980F27BEB3F100D64B0E /* PhotonActionSheetViewModel.swift in Sources */,
8A855C032D1EE9EF00C1A2F3 /* ContextMenuCoordinator.swift in Sources */,
EB9A179D20E69A7F00B12184 /* LegacyTheme.swift in Sources */,
E17BE4C42A94BA6900C5124E /* FakespotHighlightGroupView.swift in Sources */,
8A2DAD4B2CC02AA00067ECD0 /* LabelButtonHeaderView.swift in Sources */,
Expand Down Expand Up @@ -17384,6 +17399,7 @@
8CFD56892AAF06D3003157A6 /* ShoppingProductTests.swift in Sources */,
8ACA8F7629198D6400D3075D /* ThrottlerTests.swift in Sources */,
217AEF76284666D4004EED37 /* IntroViewModelTests.swift in Sources */,
8A09BCC32D22F1BE00CFDF60 /* ContextMenuCoordinatorTests.swift in Sources */,
0B7CF8872CAC1C4E00DC02F8 /* DefaultFolderHierarchyFetcherTests.swift in Sources */,
E16C76812ABDC0DB00172DB5 /* FakespotHighlightsCardViewModelTests.swift in Sources */,
1D8487B62AD6038100F7527C /* RemoteTabPanelStateTests.swift in Sources */,
Expand Down
31 changes: 16 additions & 15 deletions firefox-ios/Client/Coordinators/Browser/BrowserCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,14 @@ class BrowserCoordinator: BaseCoordinator,
func showHomepage(
overlayManager: OverlayModeManager,
isZeroSearch: Bool,
statusBarScrollDelegate: StatusBarScrollDelegate
statusBarScrollDelegate: StatusBarScrollDelegate,
toastContainer: UIView
) {
let homepageController = self.homepageViewController ?? HomepageViewController(
windowUUID: windowUUID,
overlayManager: overlayManager,
statusBarScrollDelegate: statusBarScrollDelegate
statusBarScrollDelegate: statusBarScrollDelegate,
toastContainer: toastContainer
)
guard browserViewController.embedContent(homepageController) else {
logger.log("Unable to embed new homepage", level: .debug, category: .coordinator)
Expand All @@ -171,13 +173,10 @@ class BrowserCoordinator: BaseCoordinator,
}

func showContextMenu(for configuration: ContextMenuConfiguration) {
let state = ContextMenuState(configuration: configuration)
let viewModel = PhotonActionSheetViewModel(actions: state.actions,
site: state.site,
modalStyle: .overFullScreen)
let sheet = PhotonActionSheet(viewModel: viewModel, windowUUID: windowUUID)
sheet.modalTransitionStyle = .crossDissolve
present(sheet)
let coordinator = ContextMenuCoordinator(configuration: configuration, router: router, windowUUID: windowUUID)
coordinator.parentCoordinator = self
add(child: coordinator)
coordinator.start()
}

func showEditBookmark(parentFolder: FxBookmarkNode, bookmark: FxBookmarkNode) {
Expand All @@ -202,11 +201,7 @@ class BrowserCoordinator: BaseCoordinator,

// MARK: - PrivateHomepageDelegate
func homePanelDidRequestToOpenInNewTab(with url: URL, isPrivate: Bool, selectNewTab: Bool) {
browserViewController.homePanelDidRequestToOpenInNewTab(
url,
isPrivate: isPrivate,
selectNewTab: selectNewTab
)
openInNewTab(url: url, isPrivate: isPrivate, selectNewTab: selectNewTab)
}

func switchMode() {
Expand Down Expand Up @@ -668,7 +663,13 @@ class BrowserCoordinator: BaseCoordinator,
}

// MARK: - BrowserNavigationHandler

func openInNewTab(url: URL, isPrivate: Bool, selectNewTab: Bool) {
browserViewController.homePanelDidRequestToOpenInNewTab(
url,
isPrivate: isPrivate,
selectNewTab: selectNewTab
)
}
func showShareSheet(
shareType: ShareType,
shareMessage: ShareMessage?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ protocol BrowserDelegate: AnyObject {
func showHomepage(
overlayManager: OverlayModeManager,
isZeroSearch: Bool,
statusBarScrollDelegate: StatusBarScrollDelegate
statusBarScrollDelegate: StatusBarScrollDelegate,
toastContainer: UIView
)

/// Show the private homepage to the user as part of felt privacy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ protocol BrowserNavigationHandler: AnyObject, QRCodeNavigationHandler {

/// Navigates to the edit bookmark view
func showEditBookmark(parentFolder: FxBookmarkNode, bookmark: FxBookmarkNode)

func openInNewTab(url: URL, isPrivate: Bool, selectNewTab: Bool)
}

extension BrowserNavigationHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,17 @@ class NavigationBrowserAction: Action {
}

enum NavigationBrowserActionType: ActionType {
// Native views
case tapOnTrackingProtection
case tapOnShareSheet
case tapOnCustomizeHomepage
case tapOnCell
case tapOnSettingsSection

// link related
case tapOnLink
case tapOnTrackingProtection
case tapOnOpenInNewTab

// cell related
case tapOnCell
case longPressOnCell
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,47 @@ import Foundation
enum BrowserNavigationDestination: Equatable {
// Native views
case contextMenu
case customizeHomepage
case settings(Route.SettingsSection)
case trackingProtectionSettings

// Webpage views
case link
case newTab

// System views
case shareSheet(ShareSheetConfiguration)
}

struct ShareSheetConfiguration: Equatable {
let shareType: ShareType
let shareMessage: ShareMessage?
let sourceView: UIView
let sourceRect: CGRect?
let toastContainer: UIView
let popoverArrowDirection: UIPopoverArrowDirection
}

/// This type exists as a field on the BrowserViewControllerState
struct NavigationDestination: Equatable {
let destination: BrowserNavigationDestination
let url: URL?
let isPrivate: Bool?
let selectNewTab: Bool?
let isGoogleTopSite: Bool?
let contextMenuConfiguration: ContextMenuConfiguration?

init(
_ destination: BrowserNavigationDestination,
url: URL? = nil,
isPrivate: Bool? = nil,
selectNewTab: Bool? = nil,
isGoogleTopSite: Bool? = nil,
contextMenuConfiguration: ContextMenuConfiguration? = nil
) {
self.destination = destination
self.url = url
self.isPrivate = isPrivate
self.selectNewTab = selectNewTab
self.isGoogleTopSite = isGoogleTopSite
self.contextMenuConfiguration = contextMenuConfiguration
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@ struct BrowserViewControllerState: ScreenState, Equatable {
NavigationBrowserActionType.tapOnTrackingProtection,
NavigationBrowserActionType.tapOnCell,
NavigationBrowserActionType.tapOnLink,
NavigationBrowserActionType.longPressOnCell:
NavigationBrowserActionType.longPressOnCell,
NavigationBrowserActionType.tapOnOpenInNewTab,
NavigationBrowserActionType.tapOnSettingsSection,
NavigationBrowserActionType.tapOnShareSheet:
return BrowserViewControllerState(
searchScreenState: state.searchScreenState,
showDataClearanceFlow: state.showDataClearanceFlow,
Expand All @@ -170,7 +173,6 @@ struct BrowserViewControllerState: ScreenState, Equatable {
microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action),
navigationDestination: action.navigationDestination
)

default:
return defaultState(from: state, action: action)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1378,7 +1378,8 @@ class BrowserViewController: UIViewController,
browserDelegate?.showHomepage(
overlayManager: overlayManager,
isZeroSearch: inline,
statusBarScrollDelegate: statusBarOverlay
statusBarScrollDelegate: statusBarOverlay,
toastContainer: contentContainer
)
} else {
browserDelegate?.showLegacyHomepage(
Expand Down Expand Up @@ -2114,8 +2115,8 @@ class BrowserViewController: UIViewController,
navigationHandler?.showContextMenu(for: configuration)
case .trackingProtectionSettings:
navigationHandler?.show(settings: .contentBlocker)
case .customizeHomepage:
navigationHandler?.show(settings: .homePage)
case .settings(let section):
navigationHandler?.show(settings: section)
case .link:
guard let url = type.url else {
logger.log("url should not be nil when navigating for a link type", level: .warning, category: .coordinator)
Expand All @@ -2126,6 +2127,21 @@ class BrowserViewController: UIViewController,
visitType: .link,
isGoogleTopSite: type.isGoogleTopSite ?? false
)
case .newTab:
guard let url = type.url, let isPrivate = type.isPrivate, let selectNewTab = type.selectNewTab else {
logger.log("all params need to be set to properly create a new tab", level: .warning, category: .coordinator)
return
}
navigationHandler?.openInNewTab(url: url, isPrivate: isPrivate, selectNewTab: selectNewTab)
case .shareSheet(let config):
navigationHandler?.showShareSheet(
shareType: config.shareType,
shareMessage: config.shareMessage,
sourceView: config.sourceView,
sourceRect: config.sourceRect,
toastContainer: config.toastContainer,
popoverArrowDirection: config.popoverArrowDirection
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Storage
struct ContextMenuConfiguration: Equatable {
var homepageSection: HomepageSection
var sourceView: UIView?
var toastContainer: UIView

var site: Site? {
switch item {
Expand All @@ -27,10 +28,12 @@ struct ContextMenuConfiguration: Equatable {
init(
homepageSection: HomepageSection,
item: HomepageItem? = nil,
sourceView: UIView? = nil
sourceView: UIView? = nil,
toastContainer: UIView
) {
self.homepageSection = homepageSection
self.item = item
self.sourceView = sourceView
self.toastContainer = toastContainer
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/

import Foundation
import Common

protocol ContextMenuCoordinatorDelegate: AnyObject {
func dismissFlow()
}

final class ContextMenuCoordinator: BaseCoordinator, ContextMenuCoordinatorDelegate {
weak var parentCoordinator: ParentCoordinatorDelegate?
private let windowUUID: WindowUUID
private let configuration: ContextMenuConfiguration

init(
configuration: ContextMenuConfiguration,
router: Router,
windowUUID: WindowUUID
) {
self.configuration = configuration
self.windowUUID = windowUUID
super.init(router: router)
}

func start() {
let state = ContextMenuState(configuration: configuration, windowUUID: windowUUID)
let viewModel = PhotonActionSheetViewModel(
actions: state.actions,
site: state.site,
modalStyle: .overFullScreen
)
let sheet = PhotonActionSheet(viewModel: viewModel, windowUUID: windowUUID)
sheet.coordinator = self
sheet.modalTransitionStyle = .crossDissolve
router.present(sheet)
}

func dismissFlow() {
router.dismiss(animated: true, completion: nil)
parentCoordinator?.didFinish(from: self)
}
}
Loading

0 comments on commit 4eabc8c

Please sign in to comment.