Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ final class HomepageDiffableDataSource: UICollectionViewDiffableDataSource<Homep
case privacyNotice
case messageCard(MessageCardConfiguration)
case topSite(TopSiteConfiguration, TextColor?)
case addShortcutTile(TextColor?)
case topSiteEmpty
case searchBar
case jumpBackIn(JumpBackInTabConfiguration)
Expand Down Expand Up @@ -95,6 +96,15 @@ final class HomepageDiffableDataSource: UICollectionViewDiffableDataSource<Homep
return nil
}
}

var canHandleLongPress: Bool {
switch self {
case .addShortcutTile:
return false
default:
return true
}
}
}

func updateSnapshot(
Expand Down Expand Up @@ -183,14 +193,22 @@ final class HomepageDiffableDataSource: UICollectionViewDiffableDataSource<Homep
and textColor: TextColor?
) -> TopSitesSnapshotData? {
guard topSitesState.shouldShowSection else { return nil }
let topSites: [HomeItem] = topSitesState.topSitesData.prefix(
topSitesState.numberOfRows * topSitesState.numberOfTilesPerRow
let maxVisibleItemCount = topSitesState.numberOfRows * topSitesState.numberOfTilesPerRow
guard maxVisibleItemCount > 0 else { return nil }

let topSitesItems: [HomeItem] = topSitesState.topSitesData.prefix(
maxVisibleItemCount
).compactMap {
.topSite($0, textColor)
}
guard !topSites.isEmpty else { return nil }
let allItems = topSitesState.shouldShowAddShortcutTile
? topSitesItems + [.addShortcutTile(textColor)]
: topSitesItems
let visibleItems = Array(allItems.prefix(maxVisibleItemCount))
guard !visibleItems.isEmpty else { return nil }

return TopSitesSnapshotData(
items: topSites,
items: visibleItems,
numberOfTilesPerRow: topSitesState.numberOfTilesPerRow,
shouldShowSectionHeader: topSitesState.shouldShowSectionHeader
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,10 @@ final class HomepageViewController: UIViewController,
return configuredCell(cellType: TopSiteCell.self, at: indexPath) { cell in
cell.configure(site, position: indexPath.row, theme: currentTheme, textColor: textColor)
}
case .addShortcutTile(let textColor):
return configuredCell(cellType: TopSiteCell.self, at: indexPath) { cell in
cell.configureAddShortcutTile(theme: currentTheme, textColor: textColor)
}
case .topSiteEmpty:
return configuredCell(cellType: EmptyTopSiteCell.self, at: indexPath) { cell in
cell.applyTheme(theme: currentTheme)
Expand Down Expand Up @@ -1001,7 +1005,7 @@ final class HomepageViewController: UIViewController,
)
return
}
if section.canHandleLongPress {
if section.canHandleLongPress && item.canHandleLongPress {
navigateToContextMenu(for: item, sourceView: sourceView)
}
}
Expand Down Expand Up @@ -1264,9 +1268,9 @@ final class HomepageViewController: UIViewController,
)
return
}
dispatchDidSelectCardItemAction(with: item)
switch item {
case .topSite(let config, _):
dispatchDidSelectCardItemAction(with: item)
let destination = NavigationDestination(
.link,
url: config.site.url.asURL,
Expand All @@ -1280,11 +1284,13 @@ final class HomepageViewController: UIViewController,
actionType: TopSitesActionType.tapOnHomepageTopSitesCell
)
case .searchBar:
dispatchDidSelectCardItemAction(with: item)
dispatchNavigationBrowserAction(
with: NavigationDestination(.homepageZeroSearch),
actionType: NavigationBrowserActionType.tapOnHomepageSearchBar
)
case .jumpBackIn(let config):
dispatchDidSelectCardItemAction(with: item)
store.dispatch(
JumpBackInAction(
tab: config.tab,
Expand All @@ -1293,6 +1299,7 @@ final class HomepageViewController: UIViewController,
)
)
case .bookmark(let config):
dispatchDidSelectCardItemAction(with: item)
let destination = NavigationDestination(
.link,
url: URIFixup.getURL(config.site.url),
Expand All @@ -1301,6 +1308,7 @@ final class HomepageViewController: UIViewController,
)
dispatchNavigationBrowserAction(with: destination, actionType: NavigationBrowserActionType.tapOnCell)
case .merino(let story, _):
dispatchDidSelectCardItemAction(with: item)
let destination = NavigationDestination(
.link,
url: story.url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct HomepageLayoutMeasurementCache {
let containerWidth: Double
let isLandscape: Bool
let shouldShowSection: Bool
let shouldShowAddShortcutTile: Bool
let contentSizeCategory: UIContentSizeCategory
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ final class HomepageSectionLayoutProvider: FeatureFlaggable {
containerWidth: containerWidth,
isLandscape: UIDevice.current.orientation.isLandscape,
shouldShowSection: topSitesState.shouldShowSection,
shouldShowAddShortcutTile: topSitesState.shouldShowAddShortcutTile,
contentSizeCategory: contentSizeCategory
)

Expand All @@ -655,7 +656,7 @@ final class HomepageSectionLayoutProvider: FeatureFlaggable {
}

let cellsData = topSitesState.topSitesData.prefix(maxCells)
guard !cellsData.isEmpty else {
guard !cellsData.isEmpty || topSitesState.shouldShowAddShortcutTile else {
measurementsCache.setHeight(0, for: measurementKey)
return 0
}
Expand All @@ -669,11 +670,17 @@ final class HomepageSectionLayoutProvider: FeatureFlaggable {
}

// Build array of configured cells for the data being displayed on the homepage
let allCells = cellsData.map { data in
var allCells = cellsData.map { data in
let cell = TopSiteCell()
cell.configure(data, position: 0, theme: LightTheme(), textColor: .black)
return cell
}
if topSitesState.shouldShowAddShortcutTile {
let cell = TopSiteCell()
cell.configureAddShortcutTile(theme: LightTheme(), textColor: .black)
allCells.append(cell)
}
allCells = Array(allCells.prefix(maxCells))

// Group into rows and compute each rows max height
let rowHeights = stride(from: 0, to: allCells.count, by: cols).map { start in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class TopSiteCell: UICollectionViewCell, ReusableCell {

struct UX {
static let imageBackgroundSize = CGSize(width: 60, height: 60)
static let addShortcutIconSize = CGSize(width: 24, height: 24)
static let pinIconSize = CGSize(width: 8, height: 8)
static let textSafeSpace: CGFloat = 6
static let faviconCornerRadius: CGFloat = 16
Expand All @@ -37,6 +38,11 @@ class TopSiteCell: UICollectionViewCell, ReusableCell {
return imageView
}()

private lazy var addShortcutImageView: UIImageView = .build { imageView in
imageView.image = UIImage.templateImageNamed(StandardImageIdentifiers.Large.plus)
imageView.isHidden = true
}

private lazy var descriptionWrapper: UIStackView = .build { stackView in
stackView.backgroundColor = .clear
stackView.axis = .vertical
Expand Down Expand Up @@ -106,6 +112,8 @@ class TopSiteCell: UICollectionViewCell, ReusableCell {
titleLabel.text = nil
sponsoredLabel.text = nil
pinImageView.isHidden = true
imageView.isHidden = true
addShortcutImageView.isHidden = true
imageViewConstraints.forEach { $0.constant = 0 }
}

Expand All @@ -132,6 +140,8 @@ class TopSiteCell: UICollectionViewCell, ReusableCell {
self.theme = theme
homeTopSite = topSite
titleLabel.text = topSite.title
imageView.isHidden = false
addShortcutImageView.isHidden = true
selectedOverlay.isHidden = true
accessibilityLabel = topSite.accessibilityLabel
accessibilityTraits = .link
Expand Down Expand Up @@ -173,13 +183,30 @@ class TopSiteCell: UICollectionViewCell, ReusableCell {
applyTheme(theme: theme)
}

func configureAddShortcutTile(theme: Theme, textColor: UIColor?) {
self.theme = theme
self.textColor = textColor
homeTopSite = nil
titleLabel.text = .FirefoxHomepage.Shortcuts.AddShortcut.TileTitle
sponsoredLabel.text = nil
pinImageView.isHidden = true
imageView.isHidden = true
addShortcutImageView.isHidden = false
selectedOverlay.isHidden = true
accessibilityLabel = .FirefoxHomepage.Shortcuts.AddShortcut.TileTitle
accessibilityTraits = .button

applyTheme(theme: theme)
}

// MARK: - Setup Helper methods

private func setupLayout() {
descriptionWrapper.addArrangedSubview(titleLabel)
descriptionWrapper.addArrangedSubview(sponsoredLabel)

rootContainer.addSubview(imageView)
rootContainer.addSubview(addShortcutImageView)
rootContainer.addSubview(selectedOverlay)
rootContainer.addSubview(pinImageView)
contentView.addSubview(rootContainer)
Expand All @@ -201,6 +228,11 @@ class TopSiteCell: UICollectionViewCell, ReusableCell {
selectedOverlay.trailingAnchor.constraint(equalTo: rootContainer.trailingAnchor),
selectedOverlay.bottomAnchor.constraint(equalTo: rootContainer.bottomAnchor),

addShortcutImageView.centerXAnchor.constraint(equalTo: rootContainer.centerXAnchor),
addShortcutImageView.centerYAnchor.constraint(equalTo: rootContainer.centerYAnchor),
addShortcutImageView.widthAnchor.constraint(equalToConstant: UX.addShortcutIconSize.width),
addShortcutImageView.heightAnchor.constraint(equalToConstant: UX.addShortcutIconSize.height),

pinImageView.topAnchor.constraint(equalTo: rootContainer.topAnchor),
pinImageView.leadingAnchor.constraint(equalTo: rootContainer.leadingAnchor),
pinImageView.widthAnchor.constraint(equalToConstant: UX.pinIconSize.width),
Expand Down Expand Up @@ -263,6 +295,7 @@ extension TopSiteCell: ThemeApplicable {
sponsoredLabel.textColor = textColor ?? theme.colors.textPrimary
selectedOverlay.backgroundColor = theme.colors.layer5Hover.withAlphaComponent(0.25)
pinImageView.tintColor = theme.colors.iconSecondary
addShortcutImageView.tintColor = theme.colors.iconPrimary

adjustBlur(theme: theme)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,22 @@ struct TopSitesAction: Action {
let topSites: [TopSiteConfiguration]?
let numberOfRows: Int?
let isEnabled: Bool?
let shouldShowAddShortcutTile: Bool?
let telemetryConfig: TopSitesTelemetryConfig?

init(
topSites: [TopSiteConfiguration]? = nil,
numberOfRows: Int? = nil,
isEnabled: Bool? = nil,
shouldShowAddShortcutTile: Bool? = nil,
telemetryConfig: TopSitesTelemetryConfig? = nil,
windowUUID: WindowUUID,
actionType: any ActionType
) {
self.windowUUID = windowUUID
self.actionType = actionType
self.isEnabled = isEnabled
self.shouldShowAddShortcutTile = shouldShowAddShortcutTile
self.topSites = topSites
self.numberOfRows = numberOfRows
self.telemetryConfig = telemetryConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class TopSitesMiddleware {
private let homepageTelemetry: HomepageTelemetry
private let bookmarksTelemetry: BookmarksTelemetry
private let unifiedAdsTelemetry: UnifiedAdsCallbackTelemetry
private let featureFlagsProvider: FeatureFlagProviding
private let logger: Logger
private let profile: Profile

Expand All @@ -23,6 +24,7 @@ final class TopSitesMiddleware {
homepageTelemetry: HomepageTelemetry = HomepageTelemetry(),
bookmarksTelemetry: BookmarksTelemetry = BookmarksTelemetry(),
unifiedAdsTelemetry: UnifiedAdsCallbackTelemetry = DefaultUnifiedAdsCallbackTelemetry(),
featureFlagsProvider: FeatureFlagProviding = AppContainer.shared.resolve(),
searchEnginesManager: SearchEnginesManager = AppContainer.shared.resolve(),
logger: Logger = DefaultLogger.shared
) {
Expand All @@ -37,6 +39,7 @@ final class TopSitesMiddleware {
self.homepageTelemetry = homepageTelemetry
self.bookmarksTelemetry = bookmarksTelemetry
self.unifiedAdsTelemetry = unifiedAdsTelemetry
self.featureFlagsProvider = featureFlagsProvider
self.logger = logger
self.profile = profile
}
Expand Down Expand Up @@ -120,6 +123,7 @@ final class TopSitesMiddleware {
store.dispatch(
TopSitesAction(
topSites: topSites,
shouldShowAddShortcutTile: featureFlagsProvider.isEnabled(.homepageAddShortcutTile),
windowUUID: windowUUID,
actionType: TopSitesMiddlewareActionType.retrievedUpdatedSites
)
Expand Down
Loading
Loading