From 1a82668ccc056a4c130149c252eca3760e188227 Mon Sep 17 00:00:00 2001 From: Dominik Kapusta Date: Sat, 9 Sep 2023 01:10:45 +0200 Subject: [PATCH 01/47] [WIP] Support for form factor specific favorites --- Core/BookmarksCachingSearch.swift | 4 ++-- Core/BookmarksExporter.swift | 2 +- Core/BookmarksImporter.swift | 2 +- Core/BookmarksModelsErrorHandling.swift | 5 +++++ Core/InternalUserStore.swift | 2 +- Core/LegacyBookmarksStoreMigration.swift | 2 +- DuckDuckGo.xcodeproj/project.pbxproj | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 6 +++--- .../BookmarkFoldersTableViewController.swift | 2 +- DuckDuckGo/BookmarksDataSource.swift | 2 +- DuckDuckGo/BookmarksViewController.swift | 4 ++-- DuckDuckGo/RemoteMessaging.swift | 21 ++++++++++++------- ...bViewControllerBrowsingMenuExtension.swift | 2 +- 13 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Core/BookmarksCachingSearch.swift b/Core/BookmarksCachingSearch.swift index 17b264b198..c43c3f2712 100644 --- a/Core/BookmarksCachingSearch.swift +++ b/Core/BookmarksCachingSearch.swift @@ -70,8 +70,8 @@ public class CoreDataBookmarksSearchStore: BookmarksSearchStore { fetchRequest.resultType = .dictionaryResultType fetchRequest.propertiesToFetch = [#keyPath(BookmarkEntity.title), #keyPath(BookmarkEntity.url), - #keyPath(BookmarkEntity.favoriteFolder), #keyPath(BookmarkEntity.objectID)] + fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(BookmarkEntity.favoriteFolders)] context.perform { let result = try? context.fetch(fetchRequest) as? [Dictionary] @@ -131,7 +131,7 @@ public class BookmarksCachingSearch: BookmarksStringSearch { self.init(objectID: objectID, title: title, url: url, - isFavorite: bookmark[#keyPath(BookmarkEntity.favoriteFolder)] != nil) + isFavorite: (bookmark[#keyPath(BookmarkEntity.favoriteFolders)] as? Set)?.isEmpty != true) } public func togglingFavorite() -> BookmarksStringSearchResult { diff --git a/Core/BookmarksExporter.swift b/Core/BookmarksExporter.swift index 53fb563af9..edf9473209 100644 --- a/Core/BookmarksExporter.swift +++ b/Core/BookmarksExporter.swift @@ -64,7 +64,7 @@ public struct BookmarksExporter { content.append(Template.bookmark(level: level, title: entity.title!.escapedForHTML, url: entity.url!, - isFavorite: entity.isFavorite)) + isFavorite: entity.isFavorite(on: .mobile))) } } return content diff --git a/Core/BookmarksImporter.swift b/Core/BookmarksImporter.swift index a98a7c6668..fc9cbc6f53 100644 --- a/Core/BookmarksImporter.swift +++ b/Core/BookmarksImporter.swift @@ -43,7 +43,7 @@ final public class BookmarksImporter { private(set) var coreDataStorage: BookmarkCoreDataImporter public init(coreDataStore: CoreDataDatabase) { - coreDataStorage = BookmarkCoreDataImporter(database: coreDataStore) + coreDataStorage = BookmarkCoreDataImporter(database: coreDataStore, favoritesConfiguration: .displayNative(.mobile)) } func isDocumentInSafariFormat(_ document: Document) -> Bool { diff --git a/Core/BookmarksModelsErrorHandling.swift b/Core/BookmarksModelsErrorHandling.swift index aad7935bbe..4cb4280a27 100644 --- a/Core/BookmarksModelsErrorHandling.swift +++ b/Core/BookmarksModelsErrorHandling.swift @@ -85,6 +85,7 @@ public extension BookmarkEditorViewModel { syncService: DDGSyncing?) { self.init(editingEntityID: editingEntityID, bookmarksDatabase: bookmarksDatabase, + favoritesConfiguration: .displayNative(.mobile), errorEvents: BookmarksModelsErrorHandling(syncService: syncService)) } @@ -94,6 +95,7 @@ public extension BookmarkEditorViewModel { syncService: DDGSyncing?) { self.init(creatingFolderWithParentID: parentFolderID, bookmarksDatabase: bookmarksDatabase, + favoritesConfiguration: .displayNative(.mobile), errorEvents: BookmarksModelsErrorHandling(syncService: syncService)) } } @@ -104,6 +106,7 @@ public extension BookmarkListViewModel { parentID: NSManagedObjectID?, syncService: DDGSyncing?) { self.init(bookmarksDatabase: bookmarksDatabase, + favoritesConfiguration: .displayNative(.mobile), parentID: parentID, errorEvents: BookmarksModelsErrorHandling(syncService: syncService)) } @@ -113,6 +116,7 @@ public extension FavoritesListViewModel { convenience init(bookmarksDatabase: CoreDataDatabase) { self.init(bookmarksDatabase: bookmarksDatabase, + favoritesConfiguration: .displayNative(.mobile), errorEvents: BookmarksModelsErrorHandling()) } } @@ -121,6 +125,7 @@ public extension MenuBookmarksViewModel { convenience init(bookmarksDatabase: CoreDataDatabase, syncService: DDGSyncing?) { self.init(bookmarksDatabase: bookmarksDatabase, + favoritesConfiguration: .displayNative(.mobile), errorEvents: BookmarksModelsErrorHandling(syncService: syncService)) } } diff --git a/Core/InternalUserStore.swift b/Core/InternalUserStore.swift index 5d58edb0a7..bdafe3c0c8 100644 --- a/Core/InternalUserStore.swift +++ b/Core/InternalUserStore.swift @@ -24,6 +24,6 @@ public class InternalUserStore: InternalUserStoring { public init() { } - @UserDefaultsWrapper(key: .featureFlaggingDidVerifyInternalUser, defaultValue: false) + @UserDefaultsWrapper(key: .featureFlaggingDidVerifyInternalUser, defaultValue: true) public var isInternalUser: Bool } diff --git a/Core/LegacyBookmarksStoreMigration.swift b/Core/LegacyBookmarksStoreMigration.swift index 248d96f12b..c4d20c1a45 100644 --- a/Core/LegacyBookmarksStoreMigration.swift +++ b/Core/LegacyBookmarksStoreMigration.swift @@ -82,7 +82,7 @@ public class LegacyBookmarksStoreMigration { BookmarkUtils.prepareFoldersStructure(in: destination) guard let newRoot = BookmarkUtils.fetchRootFolder(destination), - let newFavoritesRoot = BookmarkUtils.fetchFavoritesFolder(destination) else { + let newFavoritesRoot = BookmarkUtils.fetchFavoritesFolder(withUUID: FavoritesPlatform.all.rawValue, in: destination) else { Pixel.fire(pixel: .bookmarksMigrationCouldNotPrepareDatabase) Thread.sleep(forTimeInterval: 2) fatalError("Could not write to Bookmarks DB") diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 3715d07b19..6f02de073c 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -8877,8 +8877,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/DuckDuckGo/BrowserServicesKit"; requirement = { - kind = exactVersion; - version = 77.2.0; + branch = "dominik/sync-ffs-favorites"; + kind = branch; }; }; C14882EB27F211A000D59F0C /* XCRemoteSwiftPackageReference "SwiftSoup" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index a130d9919d..27b631e2ac 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,9 +14,9 @@ "package": "BrowserServicesKit", "repositoryURL": "https://github.com/DuckDuckGo/BrowserServicesKit", "state": { - "branch": null, - "revision": "42b073f8a26165e8b328a5f72501abfecdd4c666", - "version": "77.2.0" + "branch": "dominik/sync-ffs-favorites", + "revision": "550e1ad99ca9b19a5213da490a655a3b1339fab8", + "version": null } }, { diff --git a/DuckDuckGo/BookmarkFoldersTableViewController.swift b/DuckDuckGo/BookmarkFoldersTableViewController.swift index 3089476e8f..5d17909d61 100644 --- a/DuckDuckGo/BookmarkFoldersTableViewController.swift +++ b/DuckDuckGo/BookmarkFoldersTableViewController.swift @@ -159,7 +159,7 @@ class BookmarkFoldersViewController: UITableViewController { fatalError("Failed to dequeue \(FavoriteCell.reuseIdentifier) as FavoriteCell") } - cell.favoriteToggle.isOn = viewModel?.bookmark.isFavorite == true + cell.favoriteToggle.isOn = viewModel?.bookmark.isFavorite(on: .mobile) == true cell.favoriteToggle.removeTarget(self, action: #selector(favoriteToggleDidChange(_:)), for: .valueChanged) cell.favoriteToggle.addTarget(self, action: #selector(favoriteToggleDidChange(_:)), for: .valueChanged) cell.favoriteToggle.onTintColor = ThemeManager.shared.currentTheme.buttonTintColor diff --git a/DuckDuckGo/BookmarksDataSource.swift b/DuckDuckGo/BookmarksDataSource.swift index 2f7b35d626..5e9a6e5e2e 100644 --- a/DuckDuckGo/BookmarksDataSource.swift +++ b/DuckDuckGo/BookmarksDataSource.swift @@ -52,7 +52,7 @@ class BookmarksDataSource: NSObject, UITableViewDataSource { let cell = BookmarksViewControllerCellFactory.makeBookmarkCell(tableView, forIndexPath: indexPath) cell.faviconImageView.loadFavicon(forDomain: bookmark.urlObject?.host, usingCache: .fireproof) cell.titleLabel.text = bookmark.title - cell.favoriteImageViewContainer.isHidden = !bookmark.isFavorite + cell.favoriteImageViewContainer.isHidden = !bookmark.isFavorite(on: .mobile) return cell } } diff --git a/DuckDuckGo/BookmarksViewController.swift b/DuckDuckGo/BookmarksViewController.swift index f8aa5b171c..1a583f34f9 100644 --- a/DuckDuckGo/BookmarksViewController.swift +++ b/DuckDuckGo/BookmarksViewController.swift @@ -286,8 +286,8 @@ class BookmarksViewController: UIViewController, UITableViewDelegate { let cell = tableView.cellForRow(at: indexPath) cell?.tintColor = .black - let title = bookmark.isFavorite ? UserText.actionRemoveFavorite : UserText.favorite - let iconName = bookmark.isFavorite ? "Favorite-Remove-24" : "Favorite-24" + let title = bookmark.isFavorite(on: .mobile) ? UserText.actionRemoveFavorite : UserText.favorite + let iconName = bookmark.isFavorite(on: .mobile) ? "Favorite-Remove-24" : "Favorite-24" let toggleFavoriteAction = UIContextualAction(style: .normal, title: title) { [weak self] (_, _, completionHandler) in completionHandler(true) diff --git a/DuckDuckGo/RemoteMessaging.swift b/DuckDuckGo/RemoteMessaging.swift index dd0efb9808..285aa29250 100644 --- a/DuckDuckGo/RemoteMessaging.swift +++ b/DuckDuckGo/RemoteMessaging.swift @@ -103,18 +103,23 @@ struct RemoteMessaging { var favoritesCount = 0 let context = bookmarksDatabase.makeContext(concurrencyType: .privateQueueConcurrencyType) context.performAndWait { + // todo + let mobileFavoritesFolder = BookmarkUtils.fetchFavoritesFolder(withUUID: FavoritesPlatform.mobile.rawValue, in: context)! + let bookmarksCountRequest = BookmarkEntity.fetchRequest() - bookmarksCountRequest.predicate = NSPredicate(format: "%K == nil AND %K == false AND %K == false", - #keyPath(BookmarkEntity.favoriteFolder), - #keyPath(BookmarkEntity.isFolder), - #keyPath(BookmarkEntity.isPendingDeletion)) + bookmarksCountRequest.predicate = NSPredicate(format: "!(ANY %K CONTAINS %@) AND %K == false AND %K == false", + #keyPath(BookmarkEntity.favoriteFolders), + mobileFavoritesFolder, + #keyPath(BookmarkEntity.isFolder), + #keyPath(BookmarkEntity.isPendingDeletion)) bookmarksCount = (try? context.count(for: bookmarksCountRequest)) ?? 0 let favoritesCountRequest = BookmarkEntity.fetchRequest() - bookmarksCountRequest.predicate = NSPredicate(format: "%K != nil AND %K == false AND %K == false", - #keyPath(BookmarkEntity.favoriteFolder), - #keyPath(BookmarkEntity.isFolder), - #keyPath(BookmarkEntity.isPendingDeletion)) + favoritesCountRequest.predicate = NSPredicate(format: "ANY %K CONTAINS %@ AND %K == false AND %K == false", + #keyPath(BookmarkEntity.favoriteFolders), + mobileFavoritesFolder, + #keyPath(BookmarkEntity.isFolder), + #keyPath(BookmarkEntity.isPendingDeletion)) favoritesCount = (try? context.count(for: favoritesCountRequest)) ?? 0 } diff --git a/DuckDuckGo/TabViewControllerBrowsingMenuExtension.swift b/DuckDuckGo/TabViewControllerBrowsingMenuExtension.swift index a9afab2d89..804da5282e 100644 --- a/DuckDuckGo/TabViewControllerBrowsingMenuExtension.swift +++ b/DuckDuckGo/TabViewControllerBrowsingMenuExtension.swift @@ -234,7 +234,7 @@ extension TabViewController { private func buildFavoriteEntry(for link: Link, bookmark: BookmarkEntity?, with bookmarksInterface: MenuBookmarksInteracting) -> BrowsingMenuEntry { - if bookmark?.isFavorite ?? false { + if bookmark?.isFavorite(on: .mobile) ?? false { let action: () -> Void = { [weak self] in Pixel.fire(pixel: .browsingMenuRemoveFromFavorites) self?.performRemoveFavoriteAction(for: link, with: bookmarksInterface) From 3522cc7b3aa09b17adf4fc1fb27a11f435ce01fb Mon Sep 17 00:00:00 2001 From: Dominik Kapusta Date: Sun, 10 Sep 2023 08:51:09 +0200 Subject: [PATCH 02/47] Add favorites display mode switcher to settings --- Core/BookmarksImporter.swift | 4 +- Core/BookmarksModelsErrorHandling.swift | 17 +- Core/UserDefaultsPropertyWrapper.swift | 2 +- DuckDuckGo.xcodeproj/project.pbxproj | 4 + .../xcshareddata/swiftpm/Package.resolved | 2 +- .../AddOrEditBookmarkViewController.swift | 2 + DuckDuckGo/AppSettings.swift | 4 + DuckDuckGo/AppUserDefaults.swift | 54 ++++++ DuckDuckGo/Base.lproj/Settings.storyboard | 182 +++++++++++++----- DuckDuckGo/BookmarksViewController.swift | 12 +- ...tesDisplayModeSettingsViewController.swift | 96 +++++++++ DuckDuckGo/FavoritesViewController.swift | 9 +- DuckDuckGo/MainViewController.swift | 11 +- DuckDuckGo/SettingsViewController.swift | 8 + DuckDuckGo/TabSwitcherViewController.swift | 5 +- DuckDuckGo/TabViewController.swift | 6 +- Widgets/Widgets.swift | 2 +- 17 files changed, 355 insertions(+), 65 deletions(-) create mode 100644 DuckDuckGo/FavoritesDisplayModeSettingsViewController.swift diff --git a/Core/BookmarksImporter.swift b/Core/BookmarksImporter.swift index fc9cbc6f53..177dcf2955 100644 --- a/Core/BookmarksImporter.swift +++ b/Core/BookmarksImporter.swift @@ -42,8 +42,8 @@ final public class BookmarksImporter { private(set) var importedBookmarks: [BookmarkOrFolder] = [] private(set) var coreDataStorage: BookmarkCoreDataImporter - public init(coreDataStore: CoreDataDatabase) { - coreDataStorage = BookmarkCoreDataImporter(database: coreDataStore, favoritesConfiguration: .displayNative(.mobile)) + public init(coreDataStore: CoreDataDatabase, favoritesDisplayMode: FavoritesDisplayMode) { + coreDataStorage = BookmarkCoreDataImporter(database: coreDataStore, favoritesDisplayMode: favoritesDisplayMode) } func isDocumentInSafariFormat(_ document: Document) -> Bool { diff --git a/Core/BookmarksModelsErrorHandling.swift b/Core/BookmarksModelsErrorHandling.swift index 4cb4280a27..ff922ea19c 100644 --- a/Core/BookmarksModelsErrorHandling.swift +++ b/Core/BookmarksModelsErrorHandling.swift @@ -82,20 +82,22 @@ public extension BookmarkEditorViewModel { convenience init(editingEntityID: NSManagedObjectID, bookmarksDatabase: CoreDataDatabase, + favoritesDisplayMode: FavoritesDisplayMode, syncService: DDGSyncing?) { self.init(editingEntityID: editingEntityID, bookmarksDatabase: bookmarksDatabase, - favoritesConfiguration: .displayNative(.mobile), + favoritesDisplayMode: favoritesDisplayMode, errorEvents: BookmarksModelsErrorHandling(syncService: syncService)) } convenience init(creatingFolderWithParentID parentFolderID: NSManagedObjectID?, bookmarksDatabase: CoreDataDatabase, + favoritesDisplayMode: FavoritesDisplayMode, syncService: DDGSyncing?) { self.init(creatingFolderWithParentID: parentFolderID, bookmarksDatabase: bookmarksDatabase, - favoritesConfiguration: .displayNative(.mobile), + favoritesDisplayMode: favoritesDisplayMode, errorEvents: BookmarksModelsErrorHandling(syncService: syncService)) } } @@ -104,9 +106,10 @@ public extension BookmarkListViewModel { convenience init(bookmarksDatabase: CoreDataDatabase, parentID: NSManagedObjectID?, + favoritesDisplayMode: FavoritesDisplayMode, syncService: DDGSyncing?) { self.init(bookmarksDatabase: bookmarksDatabase, - favoritesConfiguration: .displayNative(.mobile), + favoritesDisplayMode: favoritesDisplayMode, parentID: parentID, errorEvents: BookmarksModelsErrorHandling(syncService: syncService)) } @@ -114,18 +117,18 @@ public extension BookmarkListViewModel { public extension FavoritesListViewModel { - convenience init(bookmarksDatabase: CoreDataDatabase) { + convenience init(bookmarksDatabase: CoreDataDatabase, favoritesDisplayMode: FavoritesDisplayMode) { self.init(bookmarksDatabase: bookmarksDatabase, - favoritesConfiguration: .displayNative(.mobile), + favoritesDisplayMode: favoritesDisplayMode, errorEvents: BookmarksModelsErrorHandling()) } } public extension MenuBookmarksViewModel { - convenience init(bookmarksDatabase: CoreDataDatabase, syncService: DDGSyncing?) { + convenience init(bookmarksDatabase: CoreDataDatabase, favoritesDisplayMode: FavoritesDisplayMode, syncService: DDGSyncing?) { self.init(bookmarksDatabase: bookmarksDatabase, - favoritesConfiguration: .displayNative(.mobile), + favoritesDisplayMode: favoritesDisplayMode, errorEvents: BookmarksModelsErrorHandling(syncService: syncService)) } } diff --git a/Core/UserDefaultsPropertyWrapper.swift b/Core/UserDefaultsPropertyWrapper.swift index 4c64b681f1..1fc255ecde 100644 --- a/Core/UserDefaultsPropertyWrapper.swift +++ b/Core/UserDefaultsPropertyWrapper.swift @@ -69,7 +69,7 @@ public struct UserDefaultsWrapper { case downloadedTrackerDataSetCount = "com.duckduckgo.app.downloadedTrackerDataSetCount" case downloadedPrivacyConfigurationCount = "com.duckduckgo.app.downloadedPrivacyConfigurationCount" case textSize = "com.duckduckgo.ios.textSize" - + case emailWaitlistShouldReceiveNotifications = "com.duckduckgo.ios.showWaitlistNotification" case unseenDownloadsAvailable = "com.duckduckgo.app.unseenDownloadsAvailable" diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 6f02de073c..6de1ca3ea3 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -254,6 +254,7 @@ 37DF000C29F9CA80002B7D3E /* SyncDataProviders in Frameworks */ = {isa = PBXBuildFile; productRef = 37DF000B29F9CA80002B7D3E /* SyncDataProviders */; }; 37DF000F29F9D635002B7D3E /* SyncBookmarksAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DF000E29F9D635002B7D3E /* SyncBookmarksAdapter.swift */; }; 37E615752A5F533E00ACD63D /* SyncCredentialsAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E615742A5F533E00ACD63D /* SyncCredentialsAdapter.swift */; }; + 37FC4C942AACF7170015F34E /* FavoritesDisplayModeSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FC4C932AACF7170015F34E /* FavoritesDisplayModeSettingsViewController.swift */; }; 37FCAAAB29911BF1000E420A /* WaitlistExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FCAAAA29911BF1000E420A /* WaitlistExtensions.swift */; }; 37FCAAB229914232000E420A /* WindowsBrowserWaitlistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FCAAB129914232000E420A /* WindowsBrowserWaitlistView.swift */; }; 37FCAAB429914C77000E420A /* WindowsWaitlistViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FCAAB329914C77000E420A /* WindowsWaitlistViewController.swift */; }; @@ -1244,6 +1245,7 @@ 37DF000929F9C416002B7D3E /* SyncMetadataDatabase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncMetadataDatabase.swift; sourceTree = ""; }; 37DF000E29F9D635002B7D3E /* SyncBookmarksAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncBookmarksAdapter.swift; sourceTree = ""; }; 37E615742A5F533E00ACD63D /* SyncCredentialsAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncCredentialsAdapter.swift; sourceTree = ""; }; + 37FC4C932AACF7170015F34E /* FavoritesDisplayModeSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesDisplayModeSettingsViewController.swift; sourceTree = ""; }; 37FCAAAA29911BF1000E420A /* WaitlistExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitlistExtensions.swift; sourceTree = ""; }; 37FCAAB129914232000E420A /* WindowsBrowserWaitlistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowsBrowserWaitlistView.swift; sourceTree = ""; }; 37FCAAB329914C77000E420A /* WindowsWaitlistViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowsWaitlistViewController.swift; sourceTree = ""; }; @@ -3658,6 +3660,7 @@ AA3D854423D9942200788410 /* AppIconSettingsViewController.swift */, 98F0FC1F21FF18E700CE77AB /* AutoClearSettingsViewController.swift */, F456B3B425810BB900B79B90 /* FireButtonAnimationSettingsViewController.swift */, + 37FC4C932AACF7170015F34E /* FavoritesDisplayModeSettingsViewController.swift */, 85449EF423FDA02800512AAF /* KeyboardSettingsViewController.swift */, 8540BD5523D9E9C20057FDD2 /* PreserveLoginsSettingsViewController.swift */, F176699D1E40BC86003D3222 /* Settings.storyboard */, @@ -6098,6 +6101,7 @@ 4B6484F327FD1E350050A7A1 /* MenuControllerView.swift in Sources */, 1EE7C299294227EC0026C8CB /* AutoconsentSettingsViewController.swift in Sources */, 1E8AD1D527C2E22900ABA377 /* DownloadsListSectionViewModel.swift in Sources */, + 37FC4C942AACF7170015F34E /* FavoritesDisplayModeSettingsViewController.swift in Sources */, 4BC6DD1C2A60E6AD001EC129 /* ReportBrokenSiteView.swift in Sources */, 31584616281AFB46004ADB8B /* AutofillLoginDetailsViewController.swift in Sources */, C1F341C72A6924100032057B /* EmailAddressPromptViewModel.swift in Sources */, diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 27b631e2ac..0e15404b22 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -15,7 +15,7 @@ "repositoryURL": "https://github.com/DuckDuckGo/BrowserServicesKit", "state": { "branch": "dominik/sync-ffs-favorites", - "revision": "550e1ad99ca9b19a5213da490a655a3b1339fab8", + "revision": "2a9237d5290e1b74c5ebcfd4fc94005184040320", "version": null } }, diff --git a/DuckDuckGo/AddOrEditBookmarkViewController.swift b/DuckDuckGo/AddOrEditBookmarkViewController.swift index ade8d739c2..ce6d36fcd2 100644 --- a/DuckDuckGo/AddOrEditBookmarkViewController.swift +++ b/DuckDuckGo/AddOrEditBookmarkViewController.swift @@ -51,6 +51,7 @@ class AddOrEditBookmarkViewController: UIViewController { self.bookmarksDatabase = bookmarksDatabase self.viewModel = BookmarkEditorViewModel(editingEntityID: editingEntityID, bookmarksDatabase: bookmarksDatabase, + favoritesDisplayMode: AppDependencyProvider.shared.appSettings.favoritesDisplayMode, syncService: syncService) self.syncService = syncService @@ -65,6 +66,7 @@ class AddOrEditBookmarkViewController: UIViewController { self.bookmarksDatabase = bookmarksDatabase self.viewModel = BookmarkEditorViewModel(creatingFolderWithParentID: parentFolderID, bookmarksDatabase: bookmarksDatabase, + favoritesDisplayMode: AppDependencyProvider.shared.appSettings.favoritesDisplayMode, syncService: syncService) self.syncService = syncService diff --git a/DuckDuckGo/AppSettings.swift b/DuckDuckGo/AppSettings.swift index 6e9a72c829..28cc0923ba 100644 --- a/DuckDuckGo/AppSettings.swift +++ b/DuckDuckGo/AppSettings.swift @@ -17,6 +17,8 @@ // limitations under the License. // +import Bookmarks + protocol AppSettings: AnyObject { var autocomplete: Bool { get set } var currentThemeName: ThemeName { get set } @@ -33,6 +35,8 @@ protocol AppSettings: AnyObject { var currentFireButtonAnimation: FireButtonAnimationType { get set } var textSize: Int { get set } + + var favoritesDisplayMode: FavoritesDisplayMode { get set } var autofillCredentialsEnabled: Bool { get set } var autofillCredentialsSavePromptShowAtLeastOnce: Bool { get set } diff --git a/DuckDuckGo/AppUserDefaults.swift b/DuckDuckGo/AppUserDefaults.swift index cdc13cbb36..11b0b4a43b 100644 --- a/DuckDuckGo/AppUserDefaults.swift +++ b/DuckDuckGo/AppUserDefaults.swift @@ -18,6 +18,7 @@ // import Foundation +import Bookmarks import Core import WidgetKit @@ -27,6 +28,7 @@ public class AppUserDefaults: AppSettings { public static let doNotSellStatusChange = Notification.Name("com.duckduckgo.app.DoNotSellStatusChange") public static let currentFireButtonAnimationChange = Notification.Name("com.duckduckgo.app.CurrentFireButtonAnimationChange") public static let textSizeChange = Notification.Name("com.duckduckgo.app.TextSizeChange") + public static let favoritesDisplayModeChange = Notification.Name("com.duckduckgo.app.FavoritesDisplayModeChange") public static let autofillEnabledChange = Notification.Name("com.duckduckgo.app.AutofillEnabledChange") public static let didVerifyInternalUser = Notification.Name("com.duckduckgo.app.DidVerifyInternalUser") public static let inspectableWebViewsToggled = Notification.Name("com.duckduckgo.app.DidToggleInspectableWebViews") @@ -60,6 +62,8 @@ public class AppUserDefaults: AppSettings { static let currentFireButtonAnimationKey = "com.duckduckgo.app.currentFireButtonAnimationKey" static let autofillCredentialsEnabled = "com.duckduckgo.ios.autofillCredentialsEnabled" + + static let favoritesDisplayMode = "com.duckduckgo.ios.favoritesDisplayMode" } private struct DebugKeys { @@ -177,6 +181,21 @@ public class AppUserDefaults: AppSettings { @UserDefaultsWrapper(key: .textSize, defaultValue: 100) var textSize: Int + var favoritesDisplayMode: FavoritesDisplayMode { + get { + if let string = userDefaults?.string(forKey: Keys.favoritesDisplayMode), + let favoritesDisplayMode = FavoritesDisplayMode(rawValue: string) { + + return favoritesDisplayMode + } else { + return .displayNative(.mobile) + } + } + set { + userDefaults?.setValue(newValue.rawValue, forKey: Keys.favoritesDisplayMode) + } + } + private func setAutofillCredentialsEnabledAutomaticallyIfNecessary() { if autofillCredentialsHasBeenEnabledAutomaticallyIfNecessary { return @@ -304,3 +323,38 @@ extension AppUserDefaults: AppConfigurationFetchStatistics { } } } + +extension FavoritesDisplayMode { + static let availableConfigurations = [FavoritesDisplayMode.displayNative(.mobile), .displayAll(native: .mobile)] + + var rawValue: String? { + switch self { + case .displayNative: + return "displayNative" + case .displayAll: + return "displayAll" + default: + return nil + } + } + + init?(rawValue: String) { + switch rawValue { + case "displayNative": + self = .displayNative(.mobile) + case "displayAll": + self = .displayAll(native: .mobile) + default: + return nil + } + } + + var displayString: String { + switch self { + case .displayNative: + return "Mobile Favorites Only" + case .displayAll: + return "All Device Favorites" + } + } +} diff --git a/DuckDuckGo/Base.lproj/Settings.storyboard b/DuckDuckGo/Base.lproj/Settings.storyboard index a84d95d565..fc345c107a 100644 --- a/DuckDuckGo/Base.lproj/Settings.storyboard +++ b/DuckDuckGo/Base.lproj/Settings.storyboard @@ -294,12 +294,40 @@ + + + + + + + + + + + + + + + + - + @@ -343,7 +371,7 @@ - + @@ -387,7 +415,7 @@ - + @@ -408,7 +436,7 @@ - + @@ -452,14 +480,14 @@ - + - + - + - + -