Skip to content

Commit

Permalink
Add setting for left and center aligning the bookmarks bar (#3342)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/0/1208400892922361/f
Tech Design URL:
CC:

## Description:
- Adds a setting to left-align or center-align the bookmarks bar.
- The setting is shown if the bookmarks is set to be visible. If the
bookmarks bar is set to ’Nevert show’ the alignment options will not be
visible



https://github.com/user-attachments/assets/81f84dbb-38a0-4b66-8e9b-1d0e9d8163b1


**Steps to test this PR**:
1. Play with the bookmarks alignment setting like the demo, and make
sure the alignment is correct.

**Definition of Done**:

* [x] Does this PR satisfy our [Definition of
Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)?

---
###### Internal references:
[Pull Request Review
Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f)
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
[Pull Request
Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f)
  • Loading branch information
jotaemepereira authored Oct 3, 2024
1 parent d1f0a77 commit 21b61be
Show file tree
Hide file tree
Showing 12 changed files with 401 additions and 59 deletions.
12 changes: 6 additions & 6 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@
3706FC93293F65D500E42796 /* PreferencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37AFCE8027DA2CA600471A10 /* PreferencesViewController.swift */; };
3706FC94293F65D500E42796 /* FireproofDomains.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B02198125E05FAC00ED7DEA /* FireproofDomains.swift */; };
3706FC95293F65D500E42796 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B677440255DBEEA00025BD8 /* Database.swift */; };
3706FC96293F65D500E42796 /* LeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5336D286915A10019DBFD /* LeftAlignedLayout.swift */; };
3706FC96293F65D500E42796 /* BookmarksBarCenterAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5336D286915A10019DBFD /* BookmarksBarCenterAlignedLayout.swift */; };
3706FC97293F65D500E42796 /* BookmarksOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B92928526670D1600AD2C21 /* BookmarksOutlineView.swift */; };
3706FC98293F65D500E42796 /* CountryList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE65482271FCD53008D1D63 /* CountryList.swift */; };
3706FC99293F65D500E42796 /* PreferencesSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CD54C427F2FDD100F1F7B9 /* PreferencesSection.swift */; };
Expand Down Expand Up @@ -1502,7 +1502,7 @@
4BE41A5E28446EAD00760399 /* BookmarksBarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE41A5D28446EAD00760399 /* BookmarksBarViewModel.swift */; };
4BE5336B286912D40019DBFD /* BookmarksBarCollectionViewItem.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BE53369286912D40019DBFD /* BookmarksBarCollectionViewItem.xib */; };
4BE5336C286912D40019DBFD /* BookmarksBarCollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5336A286912D40019DBFD /* BookmarksBarCollectionViewItem.swift */; };
4BE5336E286915A10019DBFD /* LeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5336D286915A10019DBFD /* LeftAlignedLayout.swift */; };
4BE5336E286915A10019DBFD /* BookmarksBarCenterAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5336D286915A10019DBFD /* BookmarksBarCenterAlignedLayout.swift */; };
4BE53374286E39F10019DBFD /* ChromiumKeychainPrompt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE53373286E39F10019DBFD /* ChromiumKeychainPrompt.swift */; };
4BE65474271FCD40008D1D63 /* PasswordManagementIdentityItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE6546E271FCD40008D1D63 /* PasswordManagementIdentityItemView.swift */; };
4BE65476271FCD41008D1D63 /* PasswordManagementCreditCardItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE65470271FCD40008D1D63 /* PasswordManagementCreditCardItemView.swift */; };
Expand Down Expand Up @@ -3720,7 +3720,7 @@
4BE41A5D28446EAD00760399 /* BookmarksBarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksBarViewModel.swift; sourceTree = "<group>"; };
4BE53369286912D40019DBFD /* BookmarksBarCollectionViewItem.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BookmarksBarCollectionViewItem.xib; sourceTree = "<group>"; };
4BE5336A286912D40019DBFD /* BookmarksBarCollectionViewItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksBarCollectionViewItem.swift; sourceTree = "<group>"; };
4BE5336D286915A10019DBFD /* LeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeftAlignedLayout.swift; sourceTree = "<group>"; };
4BE5336D286915A10019DBFD /* BookmarksBarCenterAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksBarCenterAlignedLayout.swift; sourceTree = "<group>"; };
4BE53373286E39F10019DBFD /* ChromiumKeychainPrompt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromiumKeychainPrompt.swift; sourceTree = "<group>"; };
4BE6546E271FCD40008D1D63 /* PasswordManagementIdentityItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordManagementIdentityItemView.swift; sourceTree = "<group>"; };
4BE65470271FCD40008D1D63 /* PasswordManagementCreditCardItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordManagementCreditCardItemView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6436,7 +6436,7 @@
848648A02C76F4B20082282D /* BookmarksBarMenuViewController.swift */,
4BD18EFF283F0BC500058124 /* BookmarksBarViewController.swift */,
4BE41A5D28446EAD00760399 /* BookmarksBarViewModel.swift */,
4BE5336D286915A10019DBFD /* LeftAlignedLayout.swift */,
4BE5336D286915A10019DBFD /* BookmarksBarCenterAlignedLayout.swift */,
8400DC4A2C6E26AE006509D2 /* ItemCachingCollectionView.swift */,
);
path = View;
Expand Down Expand Up @@ -11386,7 +11386,7 @@
3706FC94293F65D500E42796 /* FireproofDomains.swift in Sources */,
3706FC95293F65D500E42796 /* Database.swift in Sources */,
3707C71B294B5D0F00682A9F /* AutofillTabExtension.swift in Sources */,
3706FC96293F65D500E42796 /* LeftAlignedLayout.swift in Sources */,
3706FC96293F65D500E42796 /* BookmarksBarCenterAlignedLayout.swift in Sources */,
3706FC97293F65D500E42796 /* BookmarksOutlineView.swift in Sources */,
3706FC98293F65D500E42796 /* CountryList.swift in Sources */,
1DEF3BAE2BD145A9004A2FBA /* AutoClearHandler.swift in Sources */,
Expand Down Expand Up @@ -12945,7 +12945,7 @@
4B02198A25E05FAC00ED7DEA /* FireproofDomains.swift in Sources */,
4B677442255DBEEA00025BD8 /* Database.swift in Sources */,
1DDC85032B83903E00670238 /* PreferencesWebTrackingProtectionView.swift in Sources */,
4BE5336E286915A10019DBFD /* LeftAlignedLayout.swift in Sources */,
4BE5336E286915A10019DBFD /* BookmarksBarCenterAlignedLayout.swift in Sources */,
B6BCC5232AFCDABB002C5499 /* DataImportSourceViewModel.swift in Sources */,
4B92928B26670D1700AD2C21 /* BookmarksOutlineView.swift in Sources */,
4BF01C00272AE74C00884A61 /* CountryList.swift in Sources */,
Expand Down
16 changes: 8 additions & 8 deletions DuckDuckGo/BookmarksBar/View/BookmarksBar.storyboard
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="JFF-Nj-8om">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="23094" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="JFF-Nj-8om">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22690"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23094"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
Expand All @@ -23,13 +23,13 @@
</constraints>
</customView>
<scrollView wantsLayer="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="0.0" horizontalPageScroll="0.0" verticalLineScroll="0.0" verticalPageScroll="0.0" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" verticalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="D39-Of-BIh">
<rect key="frame" x="0.0" y="2" width="676" height="52"/>
<rect key="frame" x="12" y="2" width="664" height="52"/>
<clipView key="contentView" drawsBackground="NO" id="yvk-6W-sd0">
<rect key="frame" x="0.0" y="0.0" width="676" height="52"/>
<rect key="frame" x="0.0" y="0.0" width="664" height="52"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<collectionView selectable="YES" id="vwg-NL-UPk" customClass="ItemCachingCollectionView" customModule="DuckDuckGo_Privacy_Browser">
<rect key="frame" x="0.0" y="0.0" width="676" height="52"/>
<rect key="frame" x="0.0" y="0.0" width="664" height="52"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
<collectionViewLayout key="collectionViewLayout" id="YNm-eM-CbC"/>
<color key="primaryBackgroundColor" name="NavigationBarBackgroundColor"/>
Expand Down Expand Up @@ -78,7 +78,7 @@
<rect key="frame" x="10" y="26" width="65" height="28"/>
<subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="gwe-JW-nZ6">
<rect key="frame" x="4" y="3" width="16.5" height="24"/>
<rect key="frame" x="4" y="3" width="16" height="24"/>
<constraints>
<constraint firstAttribute="width" constant="16" id="TNn-Xg-utS"/>
<constraint firstAttribute="height" constant="16" id="ZuD-h5-gbG"/>
Expand Down Expand Up @@ -140,7 +140,7 @@
<constraint firstAttribute="trailing" secondItem="Mgr-xJ-Pl5" secondAttribute="trailing" constant="8" id="UCG-Ww-dsY"/>
<constraint firstAttribute="trailing" secondItem="X6g-3K-JDi" secondAttribute="trailing" id="ZaK-nU-eHk"/>
<constraint firstItem="Mgr-xJ-Pl5" firstAttribute="centerY" secondItem="R54-3G-cms" secondAttribute="centerY" constant="-1" id="eoh-hW-GcD"/>
<constraint firstItem="D39-Of-BIh" firstAttribute="leading" secondItem="R54-3G-cms" secondAttribute="leading" id="hOd-Bz-o5j"/>
<constraint firstItem="D39-Of-BIh" firstAttribute="leading" secondItem="R54-3G-cms" secondAttribute="leading" constant="12" id="hOd-Bz-o5j"/>
<constraint firstAttribute="bottom" secondItem="X6g-3K-JDi" secondAttribute="bottom" id="iWj-iC-9gW"/>
<constraint firstItem="cjE-4p-vxI" firstAttribute="centerY" secondItem="R54-3G-cms" secondAttribute="centerY" id="s3N-bi-7Hr"/>
<constraint firstItem="YdB-zl-3Cf" firstAttribute="leading" secondItem="R54-3G-cms" secondAttribute="leading" constant="10" id="zyW-Tf-ym2"/>
Expand Down Expand Up @@ -168,7 +168,7 @@
</scenes>
<resources>
<image name="Chevron-Double-Right-16" width="16" height="16"/>
<image name="square.and.arrow.down" catalog="system" width="15" height="17"/>
<image name="square.and.arrow.down" catalog="system" width="16" height="17"/>
<namedColor name="AddressBarFocusedBackgroundColor">
<color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// LeftAlignedLayout.swift
// BookmarksBarCenterAlignedLayout.swift
//
// Copyright © 2022 DuckDuckGo. All rights reserved.
//
Expand All @@ -23,15 +23,22 @@ extension NSCollectionView {

extension NSCollectionLayoutGroup {

static func leftAligned(cellSizes: [CGSize], interItemSpacing: CGFloat) -> NSCollectionLayoutGroup {
static func align(cellSizes: [CGSize], interItemSpacing: CGFloat, centered: Bool) -> NSCollectionLayoutGroup {
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(28))

return custom(layoutSize: groupSize) { environment in
let verticalPosition: CGFloat = environment.container.contentInsets.top
let totalWidth = cellSizes.map(\.width).reduce(0) { $0 == 0 ? $1 : $0 + interItemSpacing + $1 }
let maxItemHeight = cellSizes.map(\.height).max() ?? 0

var items: [NSCollectionLayoutGroupCustomItem] = []
var horizontalPosition: CGFloat = interItemSpacing
var horizontalPosition: CGFloat

if centered {
horizontalPosition = (environment.container.effectiveContentSize.width - totalWidth) / 2 + environment.container.contentInsets.leading
} else {
horizontalPosition = interItemSpacing
}

let rowItems: [NSCollectionLayoutGroupCustomItem] = cellSizes.map { size in
let origin = CGPoint(x: ceil(horizontalPosition), y: verticalPosition + (maxItemHeight - size.height) / 2)
Expand All @@ -48,9 +55,9 @@ extension NSCollectionLayoutGroup {
}
}

final class BookmarksBarLeftAlignedLayout: NSCollectionViewCompositionalLayout {
final class BookmarksBarCenterAlignedLayout: NSCollectionViewCompositionalLayout {

private static let interItemGapWidth: CGFloat = 2
private static let interItemGapWidth: CGFloat = 2.0

private var lastKnownInterItemGapIndicatorLayoutAttributes: NSCollectionViewLayoutAttributes?

Expand Down
8 changes: 8 additions & 0 deletions DuckDuckGo/BookmarksBar/View/BookmarksBarMenuFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,16 @@ struct BookmarksBarMenuFactory {
},
BlockMenuItem(title: UserText.mainMenuBookmarksShowBookmarksBarNever, isChecked: !prefs.showBookmarksBar) {
prefs.showBookmarksBar = false
},
NSMenuItem.separator(),
BlockMenuItem(title: UserText.mainMenuBookmarksLeftAlignBookmarksBar, isChecked: !prefs.centerAlignedBookmarksBarBool) {
prefs.centerAlignedBookmarksBarBool = false
},
BlockMenuItem(title: UserText.mainMenuBookmarksCenterAlignBookmarksBar, isChecked: prefs.centerAlignedBookmarksBarBool) {
prefs.centerAlignedBookmarksBarBool = true
}
])

return item
}

Expand Down
27 changes: 20 additions & 7 deletions DuckDuckGo/BookmarksBar/View/BookmarksBarViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ final class BookmarksBarViewController: NSViewController {
private let dragDropManager: BookmarkDragDropManager
private let viewModel: BookmarksBarViewModel
private let tabCollectionViewModel: TabCollectionViewModel
private let appereancePreferences: AppearancePreferencesPersistor

private var cancellables = Set<AnyCancellable>()

Expand All @@ -59,9 +60,14 @@ final class BookmarksBarViewController: NSViewController {
}!
}

init?(coder: NSCoder, tabCollectionViewModel: TabCollectionViewModel, bookmarkManager: BookmarkManager = LocalBookmarkManager.shared, dragDropManager: BookmarkDragDropManager = BookmarkDragDropManager.shared) {
init?(coder: NSCoder, tabCollectionViewModel: TabCollectionViewModel,
bookmarkManager: BookmarkManager = LocalBookmarkManager.shared,
dragDropManager: BookmarkDragDropManager = BookmarkDragDropManager.shared,
appereancePreferences: AppearancePreferencesPersistor = AppearancePreferencesUserDefaultsPersistor()
) {
self.bookmarkManager = bookmarkManager
self.dragDropManager = dragDropManager
self.appereancePreferences = appereancePreferences

self.tabCollectionViewModel = tabCollectionViewModel
self.viewModel = BookmarksBarViewModel(bookmarkManager: bookmarkManager, dragDropManager: dragDropManager, tabCollectionViewModel: tabCollectionViewModel)
Expand Down Expand Up @@ -98,7 +104,6 @@ final class BookmarksBarViewController: NSViewController {

bookmarksBarCollectionView.delegate = viewModel
bookmarksBarCollectionView.dataSource = viewModel
bookmarksBarCollectionView.collectionViewLayout = createLeftAlignedCollectionViewLayout()

view.postsFrameChangedNotifications = true
bookmarksBarCollectionView.setAccessibilityIdentifier("BookmarksBarViewController.bookmarksBarCollectionView")
Expand All @@ -120,6 +125,7 @@ final class BookmarksBarViewController: NSViewController {

subscribeToEvents()
refreshFavicons()
bookmarksBarCollectionView.collectionViewLayout = createCenterAlignedCollectionViewLayout(centered: appereancePreferences.centerAlignedBookmarksBar)
}

override func viewDidAppear() {
Expand Down Expand Up @@ -167,6 +173,13 @@ final class BookmarksBarViewController: NSViewController {
}
.store(in: &cancellables)

NotificationCenter.default.publisher(for: AppearancePreferences.Notifications.bookmarksBarAlignmentChanged)
.compactMap { $0.userInfo?[AppearancePreferences.Constants.bookmarksBarAlignmentChangedIsCenterAlignedParameter] as? Bool }
.sink { [weak self] isCenterAligned in
self?.bookmarksBarCollectionView.collectionViewLayout = self?.createCenterAlignedCollectionViewLayout(centered: isCenterAligned)
}
.store(in: &cancellables)

viewModel.$clippedItems
.receive(on: RunLoop.main)
.sink { [weak self] _ in
Expand Down Expand Up @@ -228,14 +241,14 @@ final class BookmarksBarViewController: NSViewController {

// MARK: - Layout

private func createLeftAlignedLayout() -> NSCollectionLayoutSection {
let group = NSCollectionLayoutGroup.leftAligned(cellSizes: viewModel.cellSizes, interItemSpacing: BookmarksBarViewModel.Constants.buttonSpacing)
private func createAlignedLayout(centered: Bool) -> NSCollectionLayoutSection {
let group = NSCollectionLayoutGroup.align(cellSizes: viewModel.cellSizes, interItemSpacing: BookmarksBarViewModel.Constants.buttonSpacing, centered: centered)
return NSCollectionLayoutSection(group: group)
}

private func createLeftAlignedCollectionViewLayout() -> NSCollectionViewLayout {
return BookmarksBarLeftAlignedLayout { [unowned self] _, _ in
return createLeftAlignedLayout()
private func createCenterAlignedCollectionViewLayout(centered: Bool) -> NSCollectionViewLayout {
return BookmarksBarCenterAlignedLayout { [unowned self] _, _ in
return createAlignedLayout(centered: centered && viewModel.clippedItems.isEmpty)
}
}

Expand Down
5 changes: 5 additions & 0 deletions DuckDuckGo/Common/Localizables/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ struct UserText {
static let mainMenuBookmarksShowBookmarksBarAlways = NSLocalizedString("Always Show", comment: "Preference for always showing the bookmarks bar")
static let mainMenuBookmarksShowBookmarksBarNewTabOnly = NSLocalizedString("Only Show on New Tab", comment: "Preference for only showing the bookmarks bar on new tab")
static let mainMenuBookmarksShowBookmarksBarNever = NSLocalizedString("Never Show", comment: "Preference for never showing the bookmarks bar on new tab")
static let mainMenuBookmarksLeftAlignBookmarksBar = NSLocalizedString("Align Bookmarks to Left", comment: "Preference for left aligning the bookmarks bar")
static let mainMenuBookmarksCenterAlignBookmarksBar = NSLocalizedString("Align Bookmarks to Center", comment: "Preference for center aligning the bookmarks bar")
static let preferencesBookmarksCenterAlignBookmarksBarTitle = NSLocalizedString("Align Bookmarks", comment: "Preference title aligning the bookmarks bar")
static let preferencesBookmarksCenterAlignBookmarksBar = NSLocalizedString("Center", comment: "Preference title aligning the bookmarks bar")
static let preferencesBookmarksLeftAlignBookmarksBare = NSLocalizedString("Left", comment: "Preference title aligning the bookmarks bar")

// MARK: - Main Menu -> Window
static let mainMenuWindow = NSLocalizedString("Window", comment: "Main Menu ")
Expand Down
1 change: 1 addition & 0 deletions DuckDuckGo/Common/Utilities/UserDefaultsWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ public struct UserDefaultsWrapper<T> {

case bookmarksBarPromptShown = "bookmarks.bar.prompt.shown"
case showBookmarksBar = "bookmarks.bar.show"
case centerAlignedBookmarksBar = "bookmarks.bar.center.aligned"
case lastBookmarksBarUsagePixelSendDate = "bookmarks.bar.last-usage-pixel-send-date"

case pinnedViews = "pinning.pinned-views"
Expand Down
Loading

0 comments on commit 21b61be

Please sign in to comment.