From 0d8a4c33ce5d95e87b95fedacbd42dbf9f260b0b Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 19 Apr 2021 17:02:48 -0400 Subject: [PATCH 01/43] History Sync Core History object migration and logic for success --- BraveShared/BraveStrings.swift | 5 + Client.xcodeproj/project.pbxproj | 14 + Client/Application/ClientPreferences.swift | 5 +- Client/Application/Migration.swift | 11 +- .../Browser/BrowserViewController.swift | 52 +-- .../Sync/BrowserViewController+Sync.swift | 78 +++++ .../Sync/BraveCore/BraveCoreMigrator.swift | 312 ++++++++++++------ Data/models/History.swift | 11 +- 8 files changed, 331 insertions(+), 157 deletions(-) create mode 100644 Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+Sync.swift diff --git a/BraveShared/BraveStrings.swift b/BraveShared/BraveStrings.swift index 4f7003c71d8..c4cd86e1aba 100644 --- a/BraveShared/BraveStrings.swift +++ b/BraveShared/BraveStrings.swift @@ -2189,6 +2189,11 @@ extension Strings { NSLocalizedString("sync.v2MigrationErrorMessage", tableName: "BraveShared", bundle: .braveShared, value: "Failed to migrate bookmarks. Please try again later.", comment: "Message for popup when the bookmark migration fails") + /// History Migration localization text + public static let historyMigrationErrorMessage = + NSLocalizedString("sync.historyMigrationErrorMessage", tableName: "BraveShared", bundle: .braveShared, + value: "Failed to migrate hitory. Please try again later.", + comment: "Message for popup when the history migration fails") } } diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index db71e28ed60..b12ffa1953b 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -456,6 +456,8 @@ 2F9311DA266698E600C6B74D /* DataSavedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F9311D8266698E600C6B74D /* DataSavedTests.swift */; }; 2FA01E2825F29B0900103D67 /* BenchmarkTierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E2725F29B0900103D67 /* BenchmarkTierTests.swift */; }; 2FA01E5D25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */; }; + 2FB9C2A12587E742009DA1FE /* BrowserViewController+ProductNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */; }; + 2FBCB169262784BF00F512D8 /* BrowserViewController+Sync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FBCB168262784BF00F512D8 /* BrowserViewController+Sync.swift */; }; 2FCAE2251ABB51F800877008 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FCAE21A1ABB51F800877008 /* Storage.framework */; }; 2FCAE2311ABB51F800877008 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FCAE21A1ABB51F800877008 /* Storage.framework */; }; 2FCAE25F1ABB531100877008 /* Cursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCAE2411ABB531100877008 /* Cursor.swift */; }; @@ -1953,6 +1955,8 @@ 2F9311D8266698E600C6B74D /* DataSavedTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSavedTests.swift; sourceTree = ""; }; 2FA01E2725F29B0900103D67 /* BenchmarkTierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkTierTests.swift; sourceTree = ""; }; 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShieldsActivityItemSourceProvider.swift; sourceTree = ""; }; + 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+ProductNotification.swift"; sourceTree = ""; }; + 2FBCB168262784BF00F512D8 /* BrowserViewController+Sync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+Sync.swift"; sourceTree = ""; }; 2FCAE21A1ABB51F800877008 /* Storage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Storage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2FCAE2241ABB51F800877008 /* StorageTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StorageTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 2FCAE22C1ABB51F800877008 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -4090,6 +4094,14 @@ 44C42CF9268378B1009572D7 /* BrowserIntents.intentdefinition */, ); path = Shortcuts; + sourceTree = ""; + }; + 2FBCB15C262783FD00F512D8 /* Sync */ = { + isa = PBXGroup; + children = ( + 2FBCB168262784BF00F512D8 /* BrowserViewController+Sync.swift */, + ); + path = Sync; sourceTree = ""; }; 2FCAE21B1ABB51F800877008 /* Storage */ = { @@ -4878,6 +4890,7 @@ 0A91598822B834CE00CCC119 /* BVC+Rewards.swift */, 2FFD2012260B914200E552A5 /* ProductNotifications */, 2F55443025913BAA000E4689 /* OpenSearch */, + 2FBCB15C262783FD00F512D8 /* Sync */, ); path = BrowserViewController; sourceTree = ""; @@ -6998,6 +7011,7 @@ 27D67CED24D07EB800066D83 /* BraveNewsSettingsViewController.swift in Sources */, 0A64384B24FD3F0F000E80A3 /* DomainUserScript.swift in Sources */, 4422D56321BFFB7F00BF1855 /* compile.cc in Sources */, + 2FBCB169262784BF00F512D8 /* BrowserViewController+Sync.swift in Sources */, D3C3696E1CC6B78800348A61 /* LocalRequestHelper.swift in Sources */, 27733E5826977EC40086799A /* PasscodeMigrationView.swift in Sources */, 2726637324981B600056CFE1 /* FeedSectionHeaderView.swift in Sources */, diff --git a/Client/Application/ClientPreferences.swift b/Client/Application/ClientPreferences.swift index 3e59b9d6c8f..1b5f907f1a1 100644 --- a/Client/Application/ClientPreferences.swift +++ b/Client/Application/ClientPreferences.swift @@ -223,7 +223,10 @@ extension Preferences { final class Chromium { static let syncV2BookmarksMigrationCompleted = Option(key: "chromium.migration.bookmarks", default: false) - static let syncV2BookmarksMigrationCount = Option(key: "chromium.migration.bookmarks.count", default: 0) + static let syncV2HistoryMigrationCompleted = Option(key: "chromium.migration.history", default: false) + + static let syncV2ObjectMigrationCount = Option(key: "chromium.migration.bookmarks.count", default: 0) + static let syncEnabled = Option(key: "chromium.sync.enabled", default: false) static let lastBookmarksFolderNodeId = Option(key: "chromium.last.bookmark.folder.node.id", default: nil) } diff --git a/Client/Application/Migration.swift b/Client/Application/Migration.swift index 5a9a8ae5190..9a81cf4568b 100644 --- a/Client/Application/Migration.swift +++ b/Client/Application/Migration.swift @@ -11,7 +11,12 @@ import Data private let log = Logger.browserLogger class Migration { - private(set) public static var braveCoreBookmarksMigrator: BraveCoreMigrator? + private(set) public static var braveCoreSyncObjectsMigrator: BraveCoreMigrator? + + private(set) public static var isChromiumMigrationCompleted: Bool = { + return Preferences.Chromium.syncV2BookmarksMigrationCompleted.value && + Preferences.Chromium.syncV2HistoryMigrationCompleted.value + }() static func launchMigrations(keyPrefix: String) { Preferences.migratePreferences(keyPrefix: keyPrefix) @@ -22,8 +27,8 @@ class Migration { } // `.migrate` is called in `BrowserViewController.viewDidLoad()` - if !Preferences.Chromium.syncV2BookmarksMigrationCompleted.value { - braveCoreBookmarksMigrator = BraveCoreMigrator() + if !isChromiumMigrationCompleted { + braveCoreSyncObjectsMigrator = BraveCoreMigrator() } if !Preferences.Migration.playlistV1FileSettingsLocationCompleted.value { diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index b110c349481..08bc1571b0c 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -711,24 +711,8 @@ class BrowserViewController: UIViewController { showWalletTransferExpiryPanelIfNeeded() - // We stop ever attempting migration after 3 times. - if Preferences.Chromium.syncV2BookmarksMigrationCount.value < 3 { - self.migrateToChromiumBookmarks { success in - if !success { - DispatchQueue.main.async { - let alert = UIAlertController(title: Strings.Sync.v2MigrationErrorTitle, - message: Strings.Sync.v2MigrationErrorMessage, - preferredStyle: .alert) - alert.addAction(UIAlertAction(title: Strings.OKString, style: .default, handler: nil)) - self.present(alert, animated: true) - } - } - } - } else { - // After 3 tries, we mark Migration as successful. - // There is nothing more we can do for the user other than to let them export/import bookmarks. - Preferences.Chromium.syncV2BookmarksMigrationCompleted.value = true - } + /// Perform migration to brave-core sync objects + doSyncMigration() if #available(iOS 14, *), !Preferences.DefaultBrowserIntro.defaultBrowserNotificationScheduled.value { scheduleDefaultBrowserNotification() @@ -746,38 +730,6 @@ class BrowserViewController: UIViewController { }) } - private func migrateToChromiumBookmarks(_ completion: @escaping (_ success: Bool) -> Void) { - let showInterstitialPage = { (url: URL?) -> Bool in - guard let url = url else { - log.error("Cannot open bookmarks page in new tab") - return false - } - - return BookmarksInterstitialPageHandler.showBookmarksPage(tabManager: self.tabManager, url: url) - } - - Migration.braveCoreBookmarksMigrator?.migrate({ success in - Preferences.Chromium.syncV2BookmarksMigrationCount.value += 1 - - if !success { - guard let url = BraveCoreMigrator.datedBookmarksURL else { - completion(showInterstitialPage(BraveCoreMigrator.bookmarksURL)) - return - } - - Migration.braveCoreBookmarksMigrator?.exportBookmarks(to: url) { success in - if success { - completion(showInterstitialPage(url)) - } else { - completion(showInterstitialPage(BraveCoreMigrator.bookmarksURL)) - } - } - } else { - completion(true) - } - }) - } - fileprivate let defaultBrowserNotificationId = "defaultBrowserNotification" private func scheduleDefaultBrowserNotification() { diff --git a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+Sync.swift b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+Sync.swift new file mode 100644 index 00000000000..f5b010c1b82 --- /dev/null +++ b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+Sync.swift @@ -0,0 +1,78 @@ +// Copyright 2021 The Brave Authors. All rights reserved. +// 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 Shared +import BraveShared +import Storage +import UIKit +import WebKit +import XCGLogger + +private let log = Logger.browserLogger + +// MARK: - Sync Browser Extension + +extension BrowserViewController { + + func doSyncMigration() { + // We stop ever attempting migration after 3 times. + if Preferences.Chromium.syncV2ObjectMigrationCount.value < 3 { + self.migrateToSyncObjects { success, syncType in + if !success { + DispatchQueue.main.async { + let alert = UIAlertController(title: Strings.Sync.v2MigrationErrorTitle, + message: syncType == .bookmarks ? Strings.Sync.v2MigrationErrorMessage : Strings.Sync.historyMigrationErrorMessage, + preferredStyle: .alert) + alert.addAction(UIAlertAction(title: Strings.OKString, style: .default, handler: nil)) + self.present(alert, animated: true) + } + } + } + } else { + // After 3 tries, we mark Migration as successful. + // There is nothing more we can do for the user other than to let them export/import bookmarks. + Preferences.Chromium.syncV2BookmarksMigrationCompleted.value = true + // Also marking the history migration completed after 3 tries + Preferences.Chromium.syncV2HistoryMigrationCompleted.value = true + } + } + + private func migrateToSyncObjects(_ completion: @escaping (_ success: Bool, _ type: MigrationSyncTypes?) -> Void) { + let showInterstitialPage = { (url: URL?) -> Bool in + guard let url = url else { + log.error("Cannot open bookmarks page in new tab") + return false + } + + return BookmarksInterstitialPageHandler.showBookmarksPage(tabManager: self.tabManager, url: url) + } + + Migration.braveCoreSyncObjectsMigrator?.migrate({ success, syncType in + Preferences.Chromium.syncV2ObjectMigrationCount.value += 1 + + if !success { + switch syncType { + case .bookmarks: + guard let url = BraveCoreMigrator.datedBookmarksURL else { + completion(showInterstitialPage(BraveCoreMigrator.bookmarksURL), .bookmarks) + return + } + + Migration.braveCoreSyncObjectsMigrator?.exportBookmarks(to: url) { success in + if success { + completion(showInterstitialPage(url), .bookmarks) + } else { + completion(showInterstitialPage(BraveCoreMigrator.bookmarksURL), .bookmarks) + } + } + default: + completion(false, syncType) + } + } else { + completion(true, syncType) + } + }) + } +} diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 769bf0def82..d9105156bad 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -12,14 +12,17 @@ import CoreData private let log = Logger.browserLogger +// MARK: MigrationSyncTypes + +public enum MigrationSyncTypes { + case bookmarks + case history + case all +} + class BraveCoreMigrator { - @Observable - private(set) public var migrationObserver: MigrationState = .notStarted - - private let dataImportExporter = BraveCoreImportExportUtility() - private let bookmarksAPI = BraveBookmarksAPI() - private var observer: BookmarkModelListener? + // MARK: Migration State enum MigrationState { case notStarted @@ -28,8 +31,20 @@ class BraveCoreMigrator { case completed } + @Observable + private(set) public var migrationObserver: MigrationState = .notStarted + + private var bookmarkMigrationState: MigrationState = .notStarted + private var historyMigrationState: MigrationState = .notStarted + + private let bookmarksAPI = BraveBookmarksAPI() + private let historyAPI = BraveHistoryAPI() + private let dataImportExporter = BraveCoreImportExportUtility() + private var observer: BookmarkModelListener? + public init() { - if Preferences.Chromium.syncV2BookmarksMigrationCompleted.value { + // Check If Chromium Sync Objects Migration is complete (Bookmarks-History) + if Migration.isChromiumMigrationCompleted { migrationObserver = .completed } @@ -83,113 +98,89 @@ class BraveCoreMigrator { _migrationObserver.observe(from: object, handler) } - public static var bookmarksURL: URL? { - let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) - guard let documentsDirectory = paths.first else { - log.error("Unable to access documents directory") - return nil - } - - guard let url = URL(string: "\(documentsDirectory)/Bookmarks.html") else { - log.error("Unable to access Bookmarks.html") - return nil + public func migrate(_ completion: ((_ success: Bool, _ type: MigrationSyncTypes?) -> Void)? = nil) { + // Check If Chromium Sync Objects Migration is complete (Bookmarks-History) + if Migration.isChromiumMigrationCompleted { + migrationObserver = .completed + completion?(true, .all) + return } - return url - } + // Step 1: Check If bookmarks are migrated / migrate + migrateBookmarkModels { [unowned self] success in + guard success else { + self.migrationObserver = .failed + completion?(false, .bookmarks) + + return + } - public static var datedBookmarksURL: URL? { - let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) - guard let documentsDirectory = paths.first else { - log.error("Unable to access documents directory") - return nil - } - - let dateFormatter = DateFormatter().then { - $0.dateFormat = "yyyy-MM-dd_HH:mm:ss" - } - - let dateString = dateFormatter.string(from: Date()).escape() ?? "\(Date().timeIntervalSince1970)" - - guard let url = URL(string: "\(documentsDirectory)/Bookmarks_\(dateString).html") else { - log.error("Unable to access Bookmarks_\(dateString).html") - return nil + // Step 2: Check If history is migrated / migrate + migrateHistoryModels { [unowned self] success in + guard success else { + self.migrationObserver = .failed + completion?(false, .history) + + return + } + + completion?(true, .all) + } } - - return url } +} + +// MARK: Bookmarks Migration + +extension BraveCoreMigrator { - public func migrate(_ completion: ((_ success: Bool) -> Void)? = nil) { - if Preferences.Chromium.syncV2BookmarksMigrationCompleted.value { - migrationObserver = .completed - completion?(true) - return - } - - func performMigrationIfNeeded(_ completion: ((Bool) -> Void)?) { - if !Preferences.Chromium.syncV2BookmarksMigrationCompleted.value { - log.info("Migrating to Chromium Bookmarks v1 - Exporting") - self.exportBookmarks { [weak self] success in - if success { - log.info("Migrating to Chromium Bookmarks v1 - Start") - self?.migrateBookmarks() { success in - Preferences.Chromium.syncV2BookmarksMigrationCompleted.value = success - - if let url = BraveCoreMigrator.bookmarksURL { - do { - try FileManager.default.removeItem(at: url) - } catch { - log.error("Failed to delete Bookmarks.html backup during Migration") - } - } - - completion?(success) - } - } else { - log.info("Migrating to Chromium Bookmarks v1 failed: Exporting") - completion?(success) - } + private func migrateBookmarkModels(_ completion: @escaping (Bool) -> Void) { + if !Preferences.Chromium.syncV2BookmarksMigrationCompleted.value { + // If the bookmark model has already loaded, the observer does NOT get called! + // Therefore we should continue to migrate the bookmarks + if bookmarksAPI.isLoaded { + performBookmarkMigrationIfNeeded { success in + completion(success) } } else { - completion?(true) + // Wait for the bookmark model to load before we attempt to perform migration! + self.observer = bookmarksAPI.add(BookmarksModelLoadedObserver({ [weak self] in + guard let self = self else { return } + self.observer?.destroy() + self.observer = nil + + self.performBookmarkMigrationIfNeeded { success in + completion(success) + } + })) } - } - - // If the bookmark model has already loaded, the observer does NOT get called! - // Therefore we should continue to migrate the bookmarks - if bookmarksAPI.isLoaded { - performMigrationIfNeeded({ - self.migrationObserver = $0 ? .completed : .failed - completion?($0) - }) } else { - // Wait for the bookmark model to load before we attempt to perform migration! - self.observer = bookmarksAPI.add(BookmarksModelLoadedObserver({ [weak self] in - guard let self = self else { return } - self.observer?.destroy() - self.observer = nil - - performMigrationIfNeeded({ - self.migrationObserver = $0 ? .completed : .failed - completion?($0) - }) - })) + completion(true) } } - public func exportBookmarks(to url: URL, _ completion: @escaping (_ success: Bool) -> Void) { - self.dataImportExporter.exportBookmarks(to: url, bookmarks: LegacyBookmarksHelper.getTopLevelLegacyBookmarks().sorted(by: { $0.order < $1.order })) { success in - completion(success) - } - } - - private func exportBookmarks(_ completion: @escaping (_ success: Bool) -> Void) { - guard let url = BraveCoreMigrator.bookmarksURL else { - return completion(false) - } - - self.dataImportExporter.exportBookmarks(to: url, bookmarks: LegacyBookmarksHelper.getTopLevelLegacyBookmarks().sorted(by: { $0.order < $1.order })) { success in - completion(success) + private func performBookmarkMigrationIfNeeded(_ completion: ((Bool) -> Void)?) { + log.info("Migrating to Chromium Bookmarks v1 - Exporting") + exportBookmarks { [weak self] success in + if success { + log.info("Migrating to Chromium Bookmarks v1 - Start") + self?.migrateBookmarks() { success in + Preferences.Chromium.syncV2BookmarksMigrationCompleted.value = success + + if let url = BraveCoreMigrator.bookmarksURL { + do { + try FileManager.default.removeItem(at: url) + } catch { + log.error("Failed to delete Bookmarks.html backup during Migration") + } + } + + completion?(success) + } + } else { + log.info("Migrating to Chromium Bookmarks v1 failed: Exporting") + completion?(success) + } } } @@ -261,7 +252,126 @@ class BraveCoreMigrator { } } +// MARK: - History Migration + +extension BraveCoreMigrator { + + private func migrateHistoryModels(_ completion: @escaping (Bool) -> Void) { + if !Preferences.Chromium.syncV2HistoryMigrationCompleted.value { + // If the history model has already loaded, the observer does NOT get called! + // Therefore we should continue to migrate the history + if historyAPI.isLoaded { + performHistoryMigrationIfNeeded { success in + completion(success) + } + } else { + // TODO: Add Observer for History Loading + } + } else { + completion(true) + } + } + + private func performHistoryMigrationIfNeeded(_ completion: ((Bool) -> Void)?) { + log.info("Migrating to Chromium History v1 - Start") + migrateHistory() { success in + Preferences.Chromium.syncV2HistoryMigrationCompleted.value = success + completion?(success) + } + } + + private func migrateHistory(_ completion: @escaping (_ success: Bool) -> Void) { + DataController.performOnMainContext { context in + var didSucceed = true + + for history in History.fetchAllHistory(context) { + if self.migrateChromiumHistory(context: context, history: history) { + history.delete(context: .existing(context)) + } else { + didSucceed = false + } + } + + DispatchQueue.main.async { + completion(didSucceed) + } + } + } + + private func migrateChromiumHistory(context: NSManagedObjectContext, history: History) -> Bool { + guard let title = history.title, + let absoluteUrl = history.url, let url = URL(string: absoluteUrl), + let dateAdded = history.visitedOn else { + log.error("Invalid History Specifics") + return false + } + + historyAPI.addHistory(title, url: url, dateAdded: dateAdded) + return true + } +} + +// MARK: - Bookmarks Export + extension BraveCoreMigrator { + + public static var bookmarksURL: URL? { + let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) + guard let documentsDirectory = paths.first else { + log.error("Unable to access documents directory") + return nil + } + + guard let url = URL(string: "\(documentsDirectory)/Bookmarks.html") else { + log.error("Unable to access Bookmarks.html") + return nil + } + + return url + } + + public static var datedBookmarksURL: URL? { + let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) + guard let documentsDirectory = paths.first else { + log.error("Unable to access documents directory") + return nil + } + + let dateFormatter = DateFormatter().then { + $0.dateFormat = "yyyy-MM-dd_HH:mm:ss" + } + + let dateString = dateFormatter.string(from: Date()).escape() ?? "\(Date().timeIntervalSince1970)" + + guard let url = URL(string: "\(documentsDirectory)/Bookmarks_\(dateString).html") else { + log.error("Unable to access Bookmarks_\(dateString).html") + return nil + } + + return url + } + + public func exportBookmarks(to url: URL, _ completion: @escaping (_ success: Bool) -> Void) { + self.dataImportExporter.exportBookmarks(to: url, bookmarks: LegacyBookmarksHelper.getTopLevelLegacyBookmarks().sorted(by: { $0.order < $1.order })) { success in + completion(success) + } + } + + private func exportBookmarks(_ completion: @escaping (_ success: Bool) -> Void) { + guard let url = BraveCoreMigrator.bookmarksURL else { + return completion(false) + } + + self.dataImportExporter.exportBookmarks(to: url, bookmarks: LegacyBookmarksHelper.getTopLevelLegacyBookmarks().sorted(by: { $0.order < $1.order })) { success in + completion(success) + } + } +} + +// MARK: Model Observer + +extension BraveCoreMigrator { + class BookmarksModelLoadedObserver: NSObject & BookmarkModelObserver { private let onModelLoaded: () -> Void diff --git a/Data/models/History.swift b/Data/models/History.swift index 1860cd579ef..bc2455e95ba 100644 --- a/Data/models/History.swift +++ b/Data/models/History.swift @@ -95,8 +95,8 @@ public final class History: NSManagedObject, WebsitePresentable, CRUD { return NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: "sectionIdentifier", cacheName: nil) } - public func delete() { - delete(context: .new(inMemory: false)) + public func delete(context: WriteContext? = nil) { + delete(context: context ?? .new(inMemory: false)) } public class func deleteAll(_ completionOnMain: @escaping () -> Void) { @@ -134,6 +134,13 @@ public final class History: NSManagedObject, WebsitePresentable, CRUD { return all(where: predicate, fetchLimit: 100, context: DataController.viewContext) ?? [] } + + public class func fetchAllHistory(_ context: NSManagedObjectContext? = nil, visitedAscending: Bool = false) -> [History] { + let predicate = NSPredicate(format: "visitedOn >= %@", History.thisMonth as CVarArg) + let sortDescriptors = [NSSortDescriptor(key: "visitedOn", ascending: visitedAscending)] + + return all(where: predicate, sortDescriptors: sortDescriptors, context: context ?? DataController.viewContext) ?? [] + } } // MARK: - Internal implementations From be7977f86192e36c236c5fa9a7484e25257da48c Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 20 Apr 2021 17:01:40 -0400 Subject: [PATCH 02/43] Add history interface change and delete fix --- Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift | 6 ++++-- Data/models/History.swift | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index d9105156bad..7faa2407966 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -286,7 +286,7 @@ extension BraveCoreMigrator { for history in History.fetchAllHistory(context) { if self.migrateChromiumHistory(context: context, history: history) { - history.delete(context: .existing(context)) + history.delete() } else { didSucceed = false } @@ -306,7 +306,9 @@ extension BraveCoreMigrator { return false } - historyAPI.addHistory(title, url: url, dateAdded: dateAdded) + let historyNode = HistoryNode(title: title, guid: nil, url: url, dateAdded: dateAdded) + historyAPI.addHistory(historyNode) + return true } } diff --git a/Data/models/History.swift b/Data/models/History.swift index bc2455e95ba..9a36bc480b6 100644 --- a/Data/models/History.swift +++ b/Data/models/History.swift @@ -95,8 +95,8 @@ public final class History: NSManagedObject, WebsitePresentable, CRUD { return NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: "sectionIdentifier", cacheName: nil) } - public func delete(context: WriteContext? = nil) { - delete(context: context ?? .new(inMemory: false)) + public func delete() { + delete(context: .new(inMemory: false)) } public class func deleteAll(_ completionOnMain: @escaping () -> Void) { From e3c1839c8b7a008c6f6770c5fcff3205f8982f72 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 27 Apr 2021 16:56:49 -0400 Subject: [PATCH 03/43] Adding Historyv2 Core Type History and fetchresults --- BraveCore/Local.resolved | 8 ++ Client.xcodeproj/project.pbxproj | 42 +++++- .../{ => Bookmarks}/BookmarkFetchers.swift | 0 .../BookmarkModelStateObserver.swift | 0 .../{ => Bookmarks}/Bookmarkv2.swift | 0 .../Sync/BraveCore/BraveCoreMigrator.swift | 2 +- .../BraveCore/History/HistoryFetchers.swift | 85 ++++++++++++ .../Sync/BraveCore/History/Historyv2.swift | 126 ++++++++++++++++++ .../WebFilter/{ => Bookmarks}/Bookmarks.html | 0 .../BookmarksInterstitial.swift | 0 Data/models/History.swift | 24 ---- 11 files changed, 257 insertions(+), 30 deletions(-) create mode 100644 BraveCore/Local.resolved rename Client/Frontend/Sync/BraveCore/{ => Bookmarks}/BookmarkFetchers.swift (100%) rename Client/Frontend/Sync/BraveCore/{ => Bookmarks}/BookmarkModelStateObserver.swift (100%) rename Client/Frontend/Sync/BraveCore/{ => Bookmarks}/Bookmarkv2.swift (100%) create mode 100644 Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift create mode 100644 Client/Frontend/Sync/BraveCore/History/Historyv2.swift rename Client/Frontend/Sync/WebFilter/{ => Bookmarks}/Bookmarks.html (100%) rename Client/Frontend/Sync/WebFilter/{ => Bookmarks}/BookmarksInterstitial.swift (100%) diff --git a/BraveCore/Local.resolved b/BraveCore/Local.resolved new file mode 100644 index 00000000000..6fd8b943817 --- /dev/null +++ b/BraveCore/Local.resolved @@ -0,0 +1,8 @@ +REMINDER: Your local brave-core-ios dependency has been overwritten in node_modules. Re-run bootstrap.sh when you are done testing. + +build: Debug +brave-browser: 1.23.x (77c504a6b4e661e9140d3a7d2a63706b8b659981) +brave-core: ios/sync/history (90f24d51b381878a4c967cff1d5245481e0f6fd7) + latest tag: v1.23.76 + +DO NOT COMMIT THIS FILE diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index b12ffa1953b..34dd3782364 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -470,6 +470,8 @@ 2FD0E3AF2576C48A000C773B /* SchemePermissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD0E3AE2576C48A000C773B /* SchemePermissionTests.swift */; }; 2FD0E3D62577F327000C773B /* SearchSuggestionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD0E3D52577F327000C773B /* SearchSuggestionCell.swift */; }; 2FD1C61C2639AE9100E3C25F /* BrowserViewController+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C61B2639AE9100E3C25F /* BrowserViewController+Onboarding.swift */; }; + 2FD1C60926385C6200E3C25F /* Historyv2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C60826385C6200E3C25F /* Historyv2.swift */; }; + 2FD1C60B2638823D00E3C25F /* HistoryFetchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C60A2638823D00E3C25F /* HistoryFetchers.swift */; }; 2FDB10931A9FBEC5006CF312 /* PrefsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FDB10921A9FBEC5006CF312 /* PrefsTests.swift */; }; 2FDF290825DEE265001E5C87 /* AddToPlaylistActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FDF290725DEE265001E5C87 /* AddToPlaylistActivity.swift */; }; 2FE5B42B2580216700BFDDB8 /* ShareTrackersController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5B42A2580216700BFDDB8 /* ShareTrackersController.swift */; }; @@ -1970,6 +1972,8 @@ 2FD0E3AE2576C48A000C773B /* SchemePermissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchemePermissionTests.swift; sourceTree = ""; }; 2FD0E3D52577F327000C773B /* SearchSuggestionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSuggestionCell.swift; sourceTree = ""; }; 2FD1C61B2639AE9100E3C25F /* BrowserViewController+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+Onboarding.swift"; sourceTree = ""; }; + 2FD1C60826385C6200E3C25F /* Historyv2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Historyv2.swift; sourceTree = ""; }; + 2FD1C60A2638823D00E3C25F /* HistoryFetchers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryFetchers.swift; sourceTree = ""; }; 2FDB10921A9FBEC5006CF312 /* PrefsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefsTests.swift; sourceTree = ""; }; 2FDF290725DEE265001E5C87 /* AddToPlaylistActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddToPlaylistActivity.swift; sourceTree = ""; }; 2FE5B42A2580216700BFDDB8 /* ShareTrackersController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareTrackersController.swift; sourceTree = ""; }; @@ -4175,6 +4179,34 @@ 2F676FAC260BA4860048A1DB /* blocking-summary.json */, ); path = ProductNotifications; + sourceTree = ""; + }; + 2FD1C5FA2638599100E3C25F /* Bookmarks */ = { + isa = PBXGroup; + children = ( + 5E1DF2FC253E138500F84C39 /* Bookmarkv2.swift */, + 5E9B28EA255047C80072E655 /* BookmarkModelStateObserver.swift */, + 5E9B28F6255048540072E655 /* BookmarkFetchers.swift */, + ); + path = Bookmarks; + sourceTree = ""; + }; + 2FD1C6062638599B00E3C25F /* Bookmarks */ = { + isa = PBXGroup; + children = ( + 5EE4CF442540829D00BC4509 /* BookmarksInterstitial.swift */, + 5EE4CF5A2540868E00BC4509 /* Bookmarks.html */, + ); + path = Bookmarks; + sourceTree = ""; + }; + 2FD1C60726385AEC00E3C25F /* History */ = { + isa = PBXGroup; + children = ( + 2FD1C60826385C6200E3C25F /* Historyv2.swift */, + 2FD1C60A2638823D00E3C25F /* HistoryFetchers.swift */, + ); + path = History; sourceTree = ""; }; 392ED7D51D0AEEEE009D9B62 /* Accessors */ = { @@ -4709,12 +4741,11 @@ 5E096172252B639300F3AFBB /* BraveCore */ = { isa = PBXGroup; children = ( + 2FD1C5FA2638599100E3C25F /* Bookmarks */, + 2FD1C60726385AEC00E3C25F /* History */, 5E096173252B63A300F3AFBB /* BraveCoreMigrator.swift */, 5E09617F252B63F200F3AFBB /* BraveSyncAPI+Utilities.swift */, 5E72D54E253657FF00F8D62D /* BraveCoreImportExportUtility.swift */, - 5E1DF2FC253E138500F84C39 /* Bookmarkv2.swift */, - 5E9B28EA255047C80072E655 /* BookmarkModelStateObserver.swift */, - 5E9B28F6255048540072E655 /* BookmarkFetchers.swift */, ); path = BraveCore; sourceTree = ""; @@ -4803,8 +4834,7 @@ 5EE4CF432540828D00BC4509 /* WebFilter */ = { isa = PBXGroup; children = ( - 5EE4CF442540829D00BC4509 /* BookmarksInterstitial.swift */, - 5EE4CF5A2540868E00BC4509 /* Bookmarks.html */, + 2FD1C6062638599B00E3C25F /* Bookmarks */, ); path = WebFilter; sourceTree = ""; @@ -7429,9 +7459,11 @@ A1FEEE2020BF28D900298DA2 /* Then.swift in Sources */, 27953F7723F5DF5D00B4B595 /* AboutShieldsViewController.swift in Sources */, 0A1E84442190A57F0042F782 /* SyncCameraView.swift in Sources */, + 2FD1C60926385C6200E3C25F /* Historyv2.swift in Sources */, A1CA29C420E1746A00CB9126 /* OptionSelectionViewController.swift in Sources */, 5EC594ED232C2C8F00922111 /* OnboardingWebViewController.swift in Sources */, 0A4B012420D0321A004D4011 /* UX.swift in Sources */, + 2FD1C60B2638823D00E3C25F /* HistoryFetchers.swift in Sources */, 5E9B28EB255047C80072E655 /* BookmarkModelStateObserver.swift in Sources */, 4422D55521BFFB7E00BF1855 /* nfa.cc in Sources */, 0A39FE992486604D00290ABC /* GRDGatewayAPI.m in Sources */, diff --git a/Client/Frontend/Sync/BraveCore/BookmarkFetchers.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkFetchers.swift similarity index 100% rename from Client/Frontend/Sync/BraveCore/BookmarkFetchers.swift rename to Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkFetchers.swift diff --git a/Client/Frontend/Sync/BraveCore/BookmarkModelStateObserver.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift similarity index 100% rename from Client/Frontend/Sync/BraveCore/BookmarkModelStateObserver.swift rename to Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift diff --git a/Client/Frontend/Sync/BraveCore/Bookmarkv2.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift similarity index 100% rename from Client/Frontend/Sync/BraveCore/Bookmarkv2.swift rename to Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 7faa2407966..6c7638c3df8 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -306,7 +306,7 @@ extension BraveCoreMigrator { return false } - let historyNode = HistoryNode(title: title, guid: nil, url: url, dateAdded: dateAdded) + let historyNode = HistoryNode(url: url, title: title, dateAdded: dateAdded) historyAPI.addHistory(historyNode) return true diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift new file mode 100644 index 00000000000..2b3f7e2d0bf --- /dev/null +++ b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift @@ -0,0 +1,85 @@ +// Copyright 2021 The Brave Authors. All rights reserved. +// 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 BraveRewards +import CoreData + +// MARK: - HistoryV2FetchResultsDelegate + +protocol HistoryV2FetchResultsDelegate: AnyObject { + + func controllerWillChangeContent(_ controller: HistoryV2FetchResultsController) + + func controllerDidChangeContent(_ controller: HistoryV2FetchResultsController) + + func controller(_ controller: HistoryV2FetchResultsController, didChange anObject: Any, + at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) + + func controller(_ controller: HistoryV2FetchResultsController, didChange sectionInfo: NSFetchedResultsSectionInfo, + atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) + + func controllerDidReloadContents(_ controller: HistoryV2FetchResultsController) +} + +// MARK: - HistoryV2FetchResultsController + +protocol HistoryV2FetchResultsController { + + var delegate: HistoryV2FetchResultsDelegate? { get set } + + var fetchedObjects: [Historyv2]? { get } + + var fetchedObjectsCount: Int { get } + + func performFetch(_ completion: @escaping () -> Void) + + func object(at indexPath: IndexPath) -> Historyv2? +} + +// MARK: - Historyv2Fetcher + +class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { + + // MARK: Lifecycle + + init(historyAPI: BraveHistoryAPI) { + self.historyAPI = historyAPI + super.init() + } + + // MARK: Internal + + weak var delegate: HistoryV2FetchResultsDelegate? + + var fetchedObjects: [Historyv2]? { + return historyList + } + + var fetchedObjectsCount: Int { + return historyList.count + } + + func performFetch(_ completion: @escaping () -> Void) { + historyList.removeAll() + + historyAPI?.search(withQuery: "", maxCount: 0, completion: { [weak self] historyNodeList in + guard let self = self else { return } + self.historyList = historyNodeList.map { Historyv2(with: $0) } + + completion() + }) + } + + func object(at indexPath: IndexPath) -> Historyv2? { + return historyList[safe: indexPath.row] + } + + // MARK: Private + + private weak var historyAPI: BraveHistoryAPI? + + private var historyList = [Historyv2]() +} diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift new file mode 100644 index 00000000000..c9d87d6e4f7 --- /dev/null +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -0,0 +1,126 @@ +// Copyright 2021 The Brave Authors. All rights reserved. +// 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 Data +import BraveRewards +import BraveShared +import CoreData +import Shared + +private let log = Logger.browserLogger + +// A Lightweight wrapper around BraveCore history +// with the same layout/interface as `History (from CoreData)` +class Historyv2: WebsitePresentable { + + // MARK: Lifecycle + + init(with node: HistoryNode) { + self.historyNode = node + } + + // MARK: Internal + + public var url: String? { + historyNode.url.absoluteString + } + + public var title: String? { + historyNode.title + } + + public var created: Date? { + get { + return historyNode.dateAdded + } + + set { + historyNode.dateAdded = newValue ?? Date() + } + } + + public var sectionIdentifier: String? { + if created?.compare(Historyv2.today) == ComparisonResult.orderedDescending { + return Strings.today + } else if created?.compare(Historyv2.yesterday) == ComparisonResult.orderedDescending { + return Strings.yesterday + } else if created?.compare(Historyv2.thisWeek) == ComparisonResult.orderedDescending { + return Strings.lastWeek + } else { + return Strings.lastMonth + } + } + + // MARK: Private + + private let historyNode: HistoryNode + private static let historyAPI = BraveHistoryAPI() + + private static let today = getDate(0) + private static let yesterday = getDate(-1) + private static let thisWeek = getDate(-7) + private static let thisMonth = getDate(-31) + + private class func getDate(_ dayOffset: Int) -> Date { + let calendar = Calendar(identifier: Calendar.Identifier.gregorian) + let nowComponents = calendar.dateComponents( + [Calendar.Component.year, Calendar.Component.month, Calendar.Component.day], from: Date()) + + guard let today = calendar.date(from: nowComponents) else { + return Date() + } + + return (calendar as NSCalendar).date( + byAdding: NSCalendar.Unit.day, value: dayOffset, to: today, options: []) ?? Date() + } +} + +// MARK: History Fetching + +extension Historyv2 { + + public class func add(url: URL, title: String, dateAdded: Date) { + Historyv2.historyAPI.addHistory(HistoryNode(url: url, title: title, dateAdded: dateAdded)) + } + + public static func frc(parent: Historyv2?) -> HistoryV2FetchResultsController? { + return Historyv2Fetcher(historyAPI: Historyv2.historyAPI) + } + + public func delete() { + Historyv2.historyAPI.removeHistory(historyNode) + } + + public class func deleteAll(_ completion: @escaping () -> Void) { + Historyv2.historyAPI.removeAll { + completion() + } + } + + public class func suffix(_ maxLength: Int, _ completion: @escaping ([Historyv2]) -> Void) { + Historyv2.historyAPI.search(withQuery: nil, maxCount: UInt(max(20, maxLength)), completion: { historyResults in + completion(historyResults.map { Historyv2(with: $0) }) + }) + } + + public static func byFrequency(query: String? = nil, _ completion: @escaping ([WebsitePresentable]) -> Void) { + guard let query = query, !query.isEmpty else { return } + + Historyv2.historyAPI.search(withQuery: nil, maxCount: 200, completion: { historyResults in + completion(historyResults.map { Historyv2(with: $0) }) + }) + } + + public func update(customTitle: String?, dateAdded: Date?) { + if let title = customTitle { + historyNode.title = title + } + + if let date = dateAdded { + historyNode.dateAdded = date + } + } +} diff --git a/Client/Frontend/Sync/WebFilter/Bookmarks.html b/Client/Frontend/Sync/WebFilter/Bookmarks/Bookmarks.html similarity index 100% rename from Client/Frontend/Sync/WebFilter/Bookmarks.html rename to Client/Frontend/Sync/WebFilter/Bookmarks/Bookmarks.html diff --git a/Client/Frontend/Sync/WebFilter/BookmarksInterstitial.swift b/Client/Frontend/Sync/WebFilter/Bookmarks/BookmarksInterstitial.swift similarity index 100% rename from Client/Frontend/Sync/WebFilter/BookmarksInterstitial.swift rename to Client/Frontend/Sync/WebFilter/Bookmarks/BookmarksInterstitial.swift diff --git a/Data/models/History.swift b/Data/models/History.swift index 9a36bc480b6..66c71e52dad 100644 --- a/Data/models/History.swift +++ b/Data/models/History.swift @@ -11,30 +11,6 @@ private func getDate(_ dayOffset: Int) -> Date { return (calendar as NSCalendar).date(byAdding: NSCalendar.Unit.day, value: dayOffset, to: today, options: [])! } -private var ignoredSchemes = ["about"] - -public func isIgnoredURL(_ url: URL) -> Bool { - guard let scheme = url.scheme else { return false } - - if let _ = ignoredSchemes.firstIndex(of: scheme) { - return true - } - - if url.host == "localhost" { - return true - } - - return false -} - -public func isIgnoredURL(_ url: String) -> Bool { - if let url = URL(string: url) { - return isIgnoredURL(url) - } - - return false -} - public final class History: NSManagedObject, WebsitePresentable, CRUD { @NSManaged public var title: String? From 9250127ace2f05c2317c6f4323ffc1d9fb21d82b Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 4 May 2021 12:18:36 -0400 Subject: [PATCH 04/43] Adding Listing History Feature using Brave-Core --- Client.xcodeproj/project.pbxproj | 25 ++++++- .../xcshareddata/swiftpm/Package.resolved | 9 +++ ...BrowserViewController+CoreMigration.swift} | 2 +- .../BraveCore/History/HistoryFetchers.swift | 47 +++++++++++- .../Sync/BraveCore/History/Historyv2.swift | 74 +++++++++++++++---- 5 files changed, 134 insertions(+), 23 deletions(-) rename Client/Frontend/Browser/BrowserViewController/Sync/{BrowserViewController+Sync.swift => BrowserViewController+CoreMigration.swift} (98%) diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index 34dd3782364..dc0a4703c0b 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -457,7 +457,7 @@ 2FA01E2825F29B0900103D67 /* BenchmarkTierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E2725F29B0900103D67 /* BenchmarkTierTests.swift */; }; 2FA01E5D25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */; }; 2FB9C2A12587E742009DA1FE /* BrowserViewController+ProductNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */; }; - 2FBCB169262784BF00F512D8 /* BrowserViewController+Sync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FBCB168262784BF00F512D8 /* BrowserViewController+Sync.swift */; }; + 2FBCB169262784BF00F512D8 /* BrowserViewController+CoreMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */; }; 2FCAE2251ABB51F800877008 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FCAE21A1ABB51F800877008 /* Storage.framework */; }; 2FCAE2311ABB51F800877008 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FCAE21A1ABB51F800877008 /* Storage.framework */; }; 2FCAE25F1ABB531100877008 /* Cursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCAE2411ABB531100877008 /* Cursor.swift */; }; @@ -467,6 +467,7 @@ 2FCAE2771ABB531100877008 /* SwiftData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCAE25B1ABB531100877008 /* SwiftData.swift */; }; 2FCAE2841ABB533A00877008 /* MockFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCAE2791ABB533A00877008 /* MockFiles.swift */; }; 2FCAE33E1ABB5F1800877008 /* Storage-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FCAE33D1ABB5F1800877008 /* Storage-Bridging-Header.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2FCE87D5264195EC00B98D7E /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 2FCE87D4264195EC00B98D7E /* OrderedCollections */; }; 2FD0E3AF2576C48A000C773B /* SchemePermissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD0E3AE2576C48A000C773B /* SchemePermissionTests.swift */; }; 2FD0E3D62577F327000C773B /* SearchSuggestionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD0E3D52577F327000C773B /* SearchSuggestionCell.swift */; }; 2FD1C61C2639AE9100E3C25F /* BrowserViewController+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C61B2639AE9100E3C25F /* BrowserViewController+Onboarding.swift */; }; @@ -1958,7 +1959,7 @@ 2FA01E2725F29B0900103D67 /* BenchmarkTierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkTierTests.swift; sourceTree = ""; }; 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShieldsActivityItemSourceProvider.swift; sourceTree = ""; }; 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+ProductNotification.swift"; sourceTree = ""; }; - 2FBCB168262784BF00F512D8 /* BrowserViewController+Sync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+Sync.swift"; sourceTree = ""; }; + 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+CoreMigration.swift"; sourceTree = ""; }; 2FCAE21A1ABB51F800877008 /* Storage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Storage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2FCAE2241ABB51F800877008 /* StorageTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StorageTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 2FCAE22C1ABB51F800877008 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -2812,6 +2813,7 @@ 27756A8325ACFFEB00C129AF /* pop.framework in Frameworks */, E6231C051B90A472005ABB0D /* libxml2.2.tbd in Frameworks */, E6231C011B90A44F005ABB0D /* libz.tbd in Frameworks */, + 2FCE87D5264195EC00B98D7E /* OrderedCollections in Frameworks */, 288A2D9D1AB8B3260023ABC3 /* Shared.framework in Frameworks */, 5DE7689920B3456E00FF5533 /* BraveShared.framework in Frameworks */, 2FCAE2311ABB51F800877008 /* Storage.framework in Frameworks */, @@ -4103,7 +4105,7 @@ 2FBCB15C262783FD00F512D8 /* Sync */ = { isa = PBXGroup; children = ( - 2FBCB168262784BF00F512D8 /* BrowserViewController+Sync.swift */, + 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */, ); path = Sync; sourceTree = ""; @@ -6086,6 +6088,7 @@ ); name = Client; packageProductDependencies = ( + 2FCE87D4264195EC00B98D7E /* OrderedCollections */, ); productName = Client; productReference = F84B21BE1A090F8100AAB793 /* Client.app */; @@ -6251,6 +6254,7 @@ 27F4798A25AF94B0004922E4 /* XCRemoteSwiftPackageReference "yubikit-ios" */, 27B68E5B25C88CA7002D0826 /* XCRemoteSwiftPackageReference "FeedKit" */, 277046C02684CD1E001CB097 /* XCRemoteSwiftPackageReference "PanModal" */, + 2FCE87D3264195EC00B98D7E /* XCRemoteSwiftPackageReference "swift-collections" */, ); productRefGroup = F84B21BF1A090F8100AAB793 /* Products */; projectDirPath = ""; @@ -7041,7 +7045,7 @@ 27D67CED24D07EB800066D83 /* BraveNewsSettingsViewController.swift in Sources */, 0A64384B24FD3F0F000E80A3 /* DomainUserScript.swift in Sources */, 4422D56321BFFB7F00BF1855 /* compile.cc in Sources */, - 2FBCB169262784BF00F512D8 /* BrowserViewController+Sync.swift in Sources */, + 2FBCB169262784BF00F512D8 /* BrowserViewController+CoreMigration.swift in Sources */, D3C3696E1CC6B78800348A61 /* LocalRequestHelper.swift in Sources */, 27733E5826977EC40086799A /* PasscodeMigrationView.swift in Sources */, 2726637324981B600056CFE1 /* FeedSectionHeaderView.swift in Sources */, @@ -12937,6 +12941,14 @@ minimumVersion = 3.2.0; }; }; + 2FCE87D3264195EC00B98D7E /* XCRemoteSwiftPackageReference "swift-collections" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-collections"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.0.2; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -13005,6 +13017,11 @@ package = 27F4798A25AF94B0004922E4 /* XCRemoteSwiftPackageReference "yubikit-ios" */; productName = YubiKit; }; + 2FCE87D4264195EC00B98D7E /* OrderedCollections */ = { + isa = XCSwiftPackageProductDependency; + package = 2FCE87D3264195EC00B98D7E /* XCRemoteSwiftPackageReference "swift-collections" */; + productName = OrderedCollections; + }; /* End XCSwiftPackageProductDependency section */ /* Begin XCVersionGroup section */ diff --git a/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index aaf72ade248..616b8729a14 100644 --- a/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -64,6 +64,15 @@ "version": "5.0.1" } }, + { + "package": "swift-collections", + "repositoryURL": "https://github.com/apple/swift-collections", + "state": { + "branch": null, + "revision": "3426dba9ee5c9f8e4981b0fc9d39a818d36eec28", + "version": "0.0.4" + } + }, { "package": "SwiftKeychainWrapper", "repositoryURL": "https://github.com/jrendel/SwiftKeychainWrapper", diff --git a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+Sync.swift b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift similarity index 98% rename from Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+Sync.swift rename to Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift index f5b010c1b82..4cf291fded6 100644 --- a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+Sync.swift +++ b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift @@ -12,7 +12,7 @@ import XCGLogger private let log = Logger.browserLogger -// MARK: - Sync Browser Extension +// MARK: - Core Migration Browser Extension extension BrowserViewController { diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift index 2b3f7e2d0bf..45694b081e6 100644 --- a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift +++ b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift @@ -6,6 +6,7 @@ import Foundation import BraveRewards import CoreData +import OrderedCollections // MARK: - HistoryV2FetchResultsDelegate @@ -34,9 +35,16 @@ protocol HistoryV2FetchResultsController { var fetchedObjectsCount: Int { get } + var sectionCount: Int { get } + func performFetch(_ completion: @escaping () -> Void) func object(at indexPath: IndexPath) -> Historyv2? + + func objectCount(for section: Int) -> Int + + func titleHeader(for section: Int) -> String + } // MARK: - Historyv2Fetcher @@ -62,19 +70,52 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { return historyList.count } + var sectionCount: Int { + return sectionDetails.count + } + func performFetch(_ completion: @escaping () -> Void) { historyList.removeAll() historyAPI?.search(withQuery: "", maxCount: 0, completion: { [weak self] historyNodeList in guard let self = self else { return } - self.historyList = historyNodeList.map { Historyv2(with: $0) } + self.historyList = historyNodeList.map { [unowned self] historyNode in + let historyItem = Historyv2(with: historyNode) + + for section in Historyv2.Section.allCases { + if let detailCount = self.sectionDetails[section] { + self.sectionDetails.updateValue(detailCount + 1, forKey: section) + } else { + self.sectionDetails.updateValue(0, forKey: section) + } + } + + return historyItem + } completion() }) } func object(at indexPath: IndexPath) -> Historyv2? { - return historyList[safe: indexPath.row] + var (sectionIndex, itemCount) = (0, 0) + + repeat { + itemCount += objectCount(for: sectionIndex) + + sectionIndex += 1 + } while sectionIndex == indexPath.section + + return historyList[safe: itemCount + indexPath.row] + } + + func objectCount(for section: Int) -> Int { + return sectionDetails.elements[section].value + } + + func titleHeader(for section: Int) -> String { + return sectionDetails.elements[section].key.title + } // MARK: Private @@ -82,4 +123,6 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { private weak var historyAPI: BraveHistoryAPI? private var historyList = [Historyv2]() + + private var sectionDetails: OrderedDictionary = [:] } diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index c9d87d6e4f7..d8ce08554f5 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -12,10 +12,42 @@ import Shared private let log = Logger.browserLogger +struct Historyv2Section { + var title: String + + var numberOfObjects: Int +} + // A Lightweight wrapper around BraveCore history // with the same layout/interface as `History (from CoreData)` class Historyv2: WebsitePresentable { + /// Sections in History List to be displayed + enum Section: Int, CaseIterable { + /// History happened Today + case today + /// History happened Yesterday + case yesterday + /// History happened between yesterday and end of this week + case lastWeek + /// History happaned + case thisMonth + + /// The list of titles time period + var title: String { + switch self { + case .today: + return Strings.today + case .yesterday: + return Strings.yesterday + case .lastWeek: + return Strings.lastWeek + case .thisMonth: + return Strings.lastMonth + } + } + } + // MARK: Lifecycle init(with node: HistoryNode) { @@ -42,16 +74,12 @@ class Historyv2: WebsitePresentable { } } - public var sectionIdentifier: String? { - if created?.compare(Historyv2.today) == ComparisonResult.orderedDescending { - return Strings.today - } else if created?.compare(Historyv2.yesterday) == ComparisonResult.orderedDescending { - return Strings.yesterday - } else if created?.compare(Historyv2.thisWeek) == ComparisonResult.orderedDescending { - return Strings.lastWeek - } else { - return Strings.lastMonth - } + public var domain: String? { + historyNode.url.domainURL.absoluteString + } + + public var sectionID: Section? { + fetchHistoryTimePeriod(visited: created) } // MARK: Private @@ -59,12 +87,26 @@ class Historyv2: WebsitePresentable { private let historyNode: HistoryNode private static let historyAPI = BraveHistoryAPI() - private static let today = getDate(0) - private static let yesterday = getDate(-1) - private static let thisWeek = getDate(-7) - private static let thisMonth = getDate(-31) + private func fetchHistoryTimePeriod(visited: Date?) -> Section? { + let todayOffset = 0 + let yesterdayOffset = -1 + let thisWeekOffset = -7 + let thisMonthOffset = -31 + + if created?.compare(getDate(todayOffset)) == ComparisonResult.orderedDescending { + return .today + } else if created?.compare(getDate(yesterdayOffset)) == ComparisonResult.orderedDescending { + return .yesterday + } else if created?.compare(getDate(thisWeekOffset)) == ComparisonResult.orderedDescending { + return .lastWeek + } else if created?.compare(getDate(thisMonthOffset)) == ComparisonResult.orderedDescending { + return .thisMonth + } + + return nil + } - private class func getDate(_ dayOffset: Int) -> Date { + private func getDate(_ dayOffset: Int) -> Date { let calendar = Calendar(identifier: Calendar.Identifier.gregorian) let nowComponents = calendar.dateComponents( [Calendar.Component.year, Calendar.Component.month, Calendar.Component.day], from: Date()) @@ -86,7 +128,7 @@ extension Historyv2 { Historyv2.historyAPI.addHistory(HistoryNode(url: url, title: title, dateAdded: dateAdded)) } - public static func frc(parent: Historyv2?) -> HistoryV2FetchResultsController? { + public static func frc() -> HistoryV2FetchResultsController? { return Historyv2Fetcher(historyAPI: Historyv2.historyAPI) } From e7c1b0e4efbb3b0f915e60edb6d64c80769956e6 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 4 May 2021 12:46:27 -0400 Subject: [PATCH 05/43] Adding Add Remove All from History Data Core --- Client/Frontend/Browser/BrowserViewController.swift | 2 +- Client/Frontend/Settings/Clearables.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index 08bc1571b0c..1fc254e0156 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -1843,7 +1843,7 @@ class BrowserViewController: UIViewController { // Only add history of a url which is not a localhost url if !tab.isPrivate { - History.add(tab.title ?? "", url: url) + Historyv2.add(url: url, title: tab.title ?? "", dateAdded: Date()) } } diff --git a/Client/Frontend/Settings/Clearables.swift b/Client/Frontend/Settings/Clearables.swift index f64b16bdc80..e040bef77d8 100644 --- a/Client/Frontend/Settings/Clearables.swift +++ b/Client/Frontend/Settings/Clearables.swift @@ -106,7 +106,7 @@ class HistoryClearable: Clearable { func clear() -> Success { let result = Success() - History.deleteAll { + Historyv2.deleteAll { NotificationCenter.default.post(name: .privateDataClearedHistory, object: nil) result.fill(Maybe<()>(success: ())) } From 9088a438accd1a07b8c84bd0a0bca3f3f2cc2b34 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 4 May 2021 17:21:13 -0400 Subject: [PATCH 06/43] Change Object Traverse Algorithm --- .../BraveCore/History/HistoryFetchers.swift | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift index 45694b081e6..c0f3733333a 100644 --- a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift +++ b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift @@ -63,15 +63,15 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { weak var delegate: HistoryV2FetchResultsDelegate? var fetchedObjects: [Historyv2]? { - return historyList + historyList } var fetchedObjectsCount: Int { - return historyList.count + historyList.count } var sectionCount: Int { - return sectionDetails.count + sectionDetails.elements.filter { $0.value > 0 }.count } func performFetch(_ completion: @escaping () -> Void) { @@ -79,17 +79,14 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { historyAPI?.search(withQuery: "", maxCount: 0, completion: { [weak self] historyNodeList in guard let self = self else { return } + self.historyList = historyNodeList.map { [unowned self] historyNode in let historyItem = Historyv2(with: historyNode) - for section in Historyv2.Section.allCases { - if let detailCount = self.sectionDetails[section] { - self.sectionDetails.updateValue(detailCount + 1, forKey: section) - } else { - self.sectionDetails.updateValue(0, forKey: section) - } + if let section = historyItem.sectionID, let numOfItemInSection = self.sectionDetails[section] { + self.sectionDetails.updateValue(numOfItemInSection + 1, forKey: section) } - + return historyItem } @@ -98,23 +95,22 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { } func object(at indexPath: IndexPath) -> Historyv2? { - var (sectionIndex, itemCount) = (0, 0) + let filteredDetails = sectionDetails.elements.filter { $0.value > 0 } + var totalItemIndex = 0 - repeat { - itemCount += objectCount(for: sectionIndex) - - sectionIndex += 1 - } while sectionIndex == indexPath.section - - return historyList[safe: itemCount + indexPath.row] + for sectionIndex in 0.. Int { - return sectionDetails.elements[section].value + return sectionDetails.elements[safe: section]?.value ?? 0 } func titleHeader(for section: Int) -> String { - return sectionDetails.elements[section].key.title + return sectionDetails.elements[safe: section]?.key.title ?? "" } @@ -124,5 +120,9 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { private var historyList = [Historyv2]() - private var sectionDetails: OrderedDictionary = [:] + private var sectionDetails: OrderedDictionary = [.today: 0, + .yesterday: 0, + .lastWeek: 0, + .thisMonth: 0] + } From e09812d70d57c63eb1f99cd9a41b86ead9cde453 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 10 May 2021 16:17:58 -0400 Subject: [PATCH 07/43] Adding HistoryServiceLoaded Observer to migrate existing data --- .../Sync/BraveCore/BraveCoreMigrator.swift | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 6c7638c3df8..5393a35dab2 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -40,7 +40,8 @@ class BraveCoreMigrator { private let bookmarksAPI = BraveBookmarksAPI() private let historyAPI = BraveHistoryAPI() private let dataImportExporter = BraveCoreImportExportUtility() - private var observer: BookmarkModelListener? + private var bookmarkObserver: BookmarkModelListener? + private var historyObserver: HistoryServiceListener? public init() { // Check If Chromium Sync Objects Migration is complete (Bookmarks-History) @@ -72,10 +73,10 @@ class BraveCoreMigrator { didFinishTest = true // } } else { - self.observer = self.bookmarksAPI.add(BookmarksModelLoadedObserver({ [weak self] in + self.bookmarkObserver = self.bookmarksAPI.add(BookmarksModelLoadedObserver({ [weak self] in guard let self = self else { return } - self.observer?.destroy() - self.observer = nil + self.bookmarkObserver?.destroy() + self.bookmarkObserver = nil BraveSyncAPI.shared.leaveSyncGroup() self.bookmarksAPI.removeAll() @@ -144,10 +145,10 @@ extension BraveCoreMigrator { } } else { // Wait for the bookmark model to load before we attempt to perform migration! - self.observer = bookmarksAPI.add(BookmarksModelLoadedObserver({ [weak self] in + self.bookmarkObserver = bookmarksAPI.add(BookmarksModelLoadedObserver({ [weak self] in guard let self = self else { return } - self.observer?.destroy() - self.observer = nil + self.bookmarkObserver?.destroy() + self.bookmarkObserver = nil self.performBookmarkMigrationIfNeeded { success in completion(success) @@ -265,8 +266,16 @@ extension BraveCoreMigrator { completion(success) } } else { - // TODO: Add Observer for History Loading - } + // Wait for the history service to load before we attempt to perform migration! + self.historyObserver = historyAPI.add(HistoryServiceLoadedObserver({ [weak self] in + guard let self = self else { return } + self.historyObserver?.destroy() + self.historyObserver = nil + + self.performHistoryMigrationIfNeeded { success in + completion(success) + } + })) } } else { completion(true) } @@ -385,4 +394,16 @@ extension BraveCoreMigrator { self.onModelLoaded() } } + + class HistoryServiceLoadedObserver: NSObject & HistoryServiceObserver { + private let onServiceLoaded: () -> Void + + init(_ onModelLoaded: @escaping () -> Void) { + self.onServiceLoaded = onModelLoaded + } + + func bookmarkModelLoaded() { + self.onServiceLoaded() + } + } } From 99a1c9c4b21d9dcf91940cdd4df21de4186ff30c Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 10 May 2021 17:46:18 -0400 Subject: [PATCH 08/43] Adding History Observer method interface and loaded function --- Client.xcodeproj/project.pbxproj | 8 +++- .../History/HistoryServiceStateObserver.swift | 44 +++++++++++++++++++ .../Sync/BraveCore/History/Historyv2.swift | 25 +++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index dc0a4703c0b..32b1b581b86 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -456,6 +456,7 @@ 2F9311DA266698E600C6B74D /* DataSavedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F9311D8266698E600C6B74D /* DataSavedTests.swift */; }; 2FA01E2825F29B0900103D67 /* BenchmarkTierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E2725F29B0900103D67 /* BenchmarkTierTests.swift */; }; 2FA01E5D25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */; }; + 2FA5A7582649CD9200740035 /* HistoryServiceStateObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA5A7572649CD9200740035 /* HistoryServiceStateObserver.swift */; }; 2FB9C2A12587E742009DA1FE /* BrowserViewController+ProductNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */; }; 2FBCB169262784BF00F512D8 /* BrowserViewController+CoreMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */; }; 2FCAE2251ABB51F800877008 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FCAE21A1ABB51F800877008 /* Storage.framework */; }; @@ -470,9 +471,9 @@ 2FCE87D5264195EC00B98D7E /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 2FCE87D4264195EC00B98D7E /* OrderedCollections */; }; 2FD0E3AF2576C48A000C773B /* SchemePermissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD0E3AE2576C48A000C773B /* SchemePermissionTests.swift */; }; 2FD0E3D62577F327000C773B /* SearchSuggestionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD0E3D52577F327000C773B /* SearchSuggestionCell.swift */; }; - 2FD1C61C2639AE9100E3C25F /* BrowserViewController+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C61B2639AE9100E3C25F /* BrowserViewController+Onboarding.swift */; }; 2FD1C60926385C6200E3C25F /* Historyv2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C60826385C6200E3C25F /* Historyv2.swift */; }; 2FD1C60B2638823D00E3C25F /* HistoryFetchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C60A2638823D00E3C25F /* HistoryFetchers.swift */; }; + 2FD1C61C2639AE9100E3C25F /* BrowserViewController+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C61B2639AE9100E3C25F /* BrowserViewController+Onboarding.swift */; }; 2FDB10931A9FBEC5006CF312 /* PrefsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FDB10921A9FBEC5006CF312 /* PrefsTests.swift */; }; 2FDF290825DEE265001E5C87 /* AddToPlaylistActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FDF290725DEE265001E5C87 /* AddToPlaylistActivity.swift */; }; 2FE5B42B2580216700BFDDB8 /* ShareTrackersController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5B42A2580216700BFDDB8 /* ShareTrackersController.swift */; }; @@ -1958,6 +1959,7 @@ 2F9311D8266698E600C6B74D /* DataSavedTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSavedTests.swift; sourceTree = ""; }; 2FA01E2725F29B0900103D67 /* BenchmarkTierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkTierTests.swift; sourceTree = ""; }; 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShieldsActivityItemSourceProvider.swift; sourceTree = ""; }; + 2FA5A7572649CD9200740035 /* HistoryServiceStateObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryServiceStateObserver.swift; sourceTree = ""; }; 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+ProductNotification.swift"; sourceTree = ""; }; 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+CoreMigration.swift"; sourceTree = ""; }; 2FCAE21A1ABB51F800877008 /* Storage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Storage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1972,9 +1974,9 @@ 2FCAE33D1ABB5F1800877008 /* Storage-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Storage-Bridging-Header.h"; sourceTree = ""; }; 2FD0E3AE2576C48A000C773B /* SchemePermissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchemePermissionTests.swift; sourceTree = ""; }; 2FD0E3D52577F327000C773B /* SearchSuggestionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSuggestionCell.swift; sourceTree = ""; }; - 2FD1C61B2639AE9100E3C25F /* BrowserViewController+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+Onboarding.swift"; sourceTree = ""; }; 2FD1C60826385C6200E3C25F /* Historyv2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Historyv2.swift; sourceTree = ""; }; 2FD1C60A2638823D00E3C25F /* HistoryFetchers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryFetchers.swift; sourceTree = ""; }; + 2FD1C61B2639AE9100E3C25F /* BrowserViewController+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+Onboarding.swift"; sourceTree = ""; }; 2FDB10921A9FBEC5006CF312 /* PrefsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefsTests.swift; sourceTree = ""; }; 2FDF290725DEE265001E5C87 /* AddToPlaylistActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddToPlaylistActivity.swift; sourceTree = ""; }; 2FE5B42A2580216700BFDDB8 /* ShareTrackersController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareTrackersController.swift; sourceTree = ""; }; @@ -4207,6 +4209,7 @@ children = ( 2FD1C60826385C6200E3C25F /* Historyv2.swift */, 2FD1C60A2638823D00E3C25F /* HistoryFetchers.swift */, + 2FA5A7572649CD9200740035 /* HistoryServiceStateObserver.swift */, ); path = History; sourceTree = ""; @@ -7400,6 +7403,7 @@ 27A1ABF62485568700344503 /* FlexibleSpaceSectionProvider.swift in Sources */, 279CC2D8260CF37C009B3895 /* BrowserViewController+Menu.swift in Sources */, 2703BE8B24F4508E00CBE6CD /* CreatePDFActivity.swift in Sources */, + 2FA5A7582649CD9200740035 /* HistoryServiceStateObserver.swift in Sources */, 0A43293021B1C7F50041625B /* AdBlockStats.swift in Sources */, F930CDAE2270015C00A23FE1 /* U2FExtensions.swift in Sources */, 0AEFB88722299E6A007AF600 /* AdblockerType.swift in Sources */, diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift b/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift new file mode 100644 index 00000000000..6e472e8b6ff --- /dev/null +++ b/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift @@ -0,0 +1,44 @@ +// Copyright 2021 The Brave Authors. All rights reserved. +// 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 BraveRewards + +class HistoryServiceStateObserver: NSObject, HistoryServiceObserver { + private let listener: (StateChange) -> Void + + enum StateChange { + case serviceLoaded + case serviceDeleted + case historyVisited(HistoryNode) + case historyModified(_ nodeList: [HistoryNode]) + case historyDeleted(_ nodeList: [HistoryNode], isAllHistory: Bool) + } + + init(_ listener: @escaping (StateChange) -> Void) { + self.listener = listener + } + + func historyServiceLoaded() { + listener(.serviceLoaded) + } + + func historyServiceBeingDeleted() { + listener(.serviceDeleted) + } + + func historyNodeVisited(_ historyNode: HistoryNode) { + listener(.historyVisited(historyNode)) + } + + func historyNodesModified(_ historyNodeList: [HistoryNode]) { + listener(.historyModified(historyNodeList)) + } + + func historyNodesDeleted(_ historyNodeList: [HistoryNode], isAllHistory: Bool) { + listener(.historyDeleted(historyNodeList, isAllHistory: isAllHistory)) + } + +} diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index d8ce08554f5..c4e561e4537 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -166,3 +166,28 @@ extension Historyv2 { } } } + +// MARK: Brave-Core Only + +extension Historyv2 { + + public static func waitForHistoryServiceLoaded(_ completion: @escaping () -> Void) { + if historyAPI.isLoaded { + DispatchQueue.main.async { + completion() + } + } else { + var observer: HistoryServiceListener? + observer = Historyv2.historyAPI.add(HistoryServiceStateObserver({ + if case .serviceLoaded = $0 { + observer?.destroy() + observer = nil + + DispatchQueue.main.async { + completion() + } + } + })) + } + } +} From 1e67cfee16663e0897cc5e3a036b8a8bfcfe77f3 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Wed, 12 May 2021 11:34:28 -0400 Subject: [PATCH 09/43] Adding Service Listener Observer --- Client/Frontend/Settings/Clearables.swift | 9 ++++++--- .../BraveCore/History/HistoryFetchers.swift | 20 ++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/Client/Frontend/Settings/Clearables.swift b/Client/Frontend/Settings/Clearables.swift index e040bef77d8..049ea9978ad 100644 --- a/Client/Frontend/Settings/Clearables.swift +++ b/Client/Frontend/Settings/Clearables.swift @@ -106,9 +106,12 @@ class HistoryClearable: Clearable { func clear() -> Success { let result = Success() - Historyv2.deleteAll { - NotificationCenter.default.post(name: .privateDataClearedHistory, object: nil) - result.fill(Maybe<()>(success: ())) + + DispatchQueue.main.async { + Historyv2.deleteAll { + NotificationCenter.default.post(name: .privateDataClearedHistory, object: nil) + result.fill(Maybe<()>(success: ())) + } } return result } diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift index c0f3733333a..a3311f67eb4 100644 --- a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift +++ b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift @@ -56,6 +56,14 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { init(historyAPI: BraveHistoryAPI) { self.historyAPI = historyAPI super.init() + + self.historyServiceListener = historyAPI.add(HistoryServiceStateObserver { [weak self] _ in + guard let self = self else { return } + + DispatchQueue.main.async { + self.delegate?.controllerDidReloadContents(self) + } + }) } // MARK: Internal @@ -75,7 +83,7 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { } func performFetch(_ completion: @escaping () -> Void) { - historyList.removeAll() + clearHistoryData() historyAPI?.search(withQuery: "", maxCount: 0, completion: { [weak self] historyNodeList in guard let self = self else { return } @@ -116,6 +124,8 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { // MARK: Private + private var historyServiceListener: HistoryServiceListener? + private weak var historyAPI: BraveHistoryAPI? private var historyList = [Historyv2]() @@ -125,4 +135,12 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { .lastWeek: 0, .thisMonth: 0] + private func clearHistoryData() { + historyList.removeAll() + + for key in sectionDetails.keys { + sectionDetails.updateValue(0, forKey: key) + } + } + } From dd0cd8eea6da52015ab4dcff527c6aedafcdd323 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 17 May 2021 17:43:29 -0400 Subject: [PATCH 10/43] Adding Loaded Observer for setting up types of sync --- Client.xcodeproj/project.pbxproj | 4 +++ Client/Application/Migration.swift | 21 +++++++++++++++- .../BookmarkModelStateObserver.swift | 6 ++++- .../Sync/BraveCore/BraveCoreMigrator.swift | 2 +- .../BraveCore/BraveServiceStateObserver.swift | 25 +++++++++++++++++++ .../History/HistoryServiceStateObserver.swift | 7 +++++- 6 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 Client/Frontend/Sync/BraveCore/BraveServiceStateObserver.swift diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index 32b1b581b86..7ea1c7ea6ba 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -457,6 +457,7 @@ 2FA01E2825F29B0900103D67 /* BenchmarkTierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E2725F29B0900103D67 /* BenchmarkTierTests.swift */; }; 2FA01E5D25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */; }; 2FA5A7582649CD9200740035 /* HistoryServiceStateObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA5A7572649CD9200740035 /* HistoryServiceStateObserver.swift */; }; + 2FB0E26C2653132500B722AF /* BraveServiceStateObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB0E26B2653132500B722AF /* BraveServiceStateObserver.swift */; }; 2FB9C2A12587E742009DA1FE /* BrowserViewController+ProductNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */; }; 2FBCB169262784BF00F512D8 /* BrowserViewController+CoreMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */; }; 2FCAE2251ABB51F800877008 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FCAE21A1ABB51F800877008 /* Storage.framework */; }; @@ -1960,6 +1961,7 @@ 2FA01E2725F29B0900103D67 /* BenchmarkTierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BenchmarkTierTests.swift; sourceTree = ""; }; 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShieldsActivityItemSourceProvider.swift; sourceTree = ""; }; 2FA5A7572649CD9200740035 /* HistoryServiceStateObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryServiceStateObserver.swift; sourceTree = ""; }; + 2FB0E26B2653132500B722AF /* BraveServiceStateObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BraveServiceStateObserver.swift; sourceTree = ""; }; 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+ProductNotification.swift"; sourceTree = ""; }; 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+CoreMigration.swift"; sourceTree = ""; }; 2FCAE21A1ABB51F800877008 /* Storage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Storage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -4751,6 +4753,7 @@ 5E096173252B63A300F3AFBB /* BraveCoreMigrator.swift */, 5E09617F252B63F200F3AFBB /* BraveSyncAPI+Utilities.swift */, 5E72D54E253657FF00F8D62D /* BraveCoreImportExportUtility.swift */, + 2FB0E26B2653132500B722AF /* BraveServiceStateObserver.swift */, ); path = BraveCore; sourceTree = ""; @@ -7134,6 +7137,7 @@ 0A1E843D2190A57F0042F782 /* SyncSettingsTableViewController.swift in Sources */, 4422D56C21BFFB7F00BF1855 /* bitstate.cc in Sources */, D314E7F71A37B98700426A76 /* BottomToolbarView.swift in Sources */, + 2FB0E26C2653132500B722AF /* BraveServiceStateObserver.swift in Sources */, 4422D55321BFFB7E00BF1855 /* parse.cc in Sources */, 4422D4F421BFFB7600BF1855 /* version_edit.cc in Sources */, EB11A1062044A90E0018F749 /* ContentBlockerHelper+TabContentScript.swift in Sources */, diff --git a/Client/Application/Migration.swift b/Client/Application/Migration.swift index 9a81cf4568b..1c90f34c275 100644 --- a/Client/Application/Migration.swift +++ b/Client/Application/Migration.swift @@ -7,12 +7,15 @@ import Shared import BraveShared import SwiftKeychainWrapper import Data +import BraveRewards private let log = Logger.browserLogger class Migration { - private(set) public static var braveCoreSyncObjectsMigrator: BraveCoreMigrator? + private(set) public static var braveCoreSyncObjectsMigrator: BraveCoreMigrator? + private(set) public static var profileSyncService: BraveSyncProfileService? + private(set) public static var isChromiumMigrationCompleted: Bool = { return Preferences.Chromium.syncV2BookmarksMigrationCompleted.value && Preferences.Chromium.syncV2HistoryMigrationCompleted.value @@ -39,6 +42,22 @@ class Migration { FaviconMO.clearTooLargeFavicons() Preferences.Migration.removeLargeFaviconsMigrationCompleted.value = true } + + // Adding Observer to enable sync types + + NotificationCenter.default.addObserver( + self, + selector: #selector(enableUserSelectedTypesForSync), name: NSNotification.Name(rawValue: BraveServiceStateObserver.coreServiceLoadedNotification), + object: nil) + } + + @objc private func enableUserSelectedTypesForSync() { + guard BraveSyncAPI.shared.isInSyncGroup else { + log.info("Sync is not active") + return + } + + BraveSyncProfileService.shared.userSelectedTypes = [.HISTORY, .BOOKMARKS] } static func moveDatabaseToApplicationDirectory() { diff --git a/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift index d4e4bf0e639..ed7e9590525 100644 --- a/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift +++ b/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift @@ -6,7 +6,7 @@ import Foundation import BraveRewards -class BookmarkModelStateObserver: NSObject, BookmarkModelObserver { +class BookmarkModelStateObserver: BraveServiceStateObserver, BookmarkModelObserver { private let listener: (StateChange) -> Void enum StateChange { @@ -25,6 +25,10 @@ class BookmarkModelStateObserver: NSObject, BookmarkModelObserver { func bookmarkModelLoaded() { self.listener(.modelLoaded) + + if !BraveServiceStateObserver.isServiceLoadStatePosted { + postServiceLoadedNotification() + } } func bookmarkNodeChanged(_ bookmarkNode: BookmarkNode) { diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 5393a35dab2..8d208fe6612 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -402,7 +402,7 @@ extension BraveCoreMigrator { self.onServiceLoaded = onModelLoaded } - func bookmarkModelLoaded() { + func historyServiceLoaded() { self.onServiceLoaded() } } diff --git a/Client/Frontend/Sync/BraveCore/BraveServiceStateObserver.swift b/Client/Frontend/Sync/BraveCore/BraveServiceStateObserver.swift new file mode 100644 index 00000000000..2941317567b --- /dev/null +++ b/Client/Frontend/Sync/BraveCore/BraveServiceStateObserver.swift @@ -0,0 +1,25 @@ +// Copyright 2021 The Brave Authors. All rights reserved. +// 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 + +class BraveServiceStateObserver: NSObject { + + // MARK: Static + + static let coreServiceLoadedNotification = "BraveServiceStateDidLoaded" + + static var isServiceLoadStatePosted = false + + // MARK: Private + + func postServiceLoadedNotification() { + NotificationCenter.default.post( + name: Notification.Name(rawValue: BraveServiceStateObserver.coreServiceLoadedNotification), + object: nil) + + BraveServiceStateObserver.isServiceLoadStatePosted = true + } +} diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift b/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift index 6e472e8b6ff..a71c0267559 100644 --- a/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift +++ b/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift @@ -6,7 +6,7 @@ import Foundation import BraveRewards -class HistoryServiceStateObserver: NSObject, HistoryServiceObserver { +class HistoryServiceStateObserver: BraveServiceStateObserver, HistoryServiceObserver { private let listener: (StateChange) -> Void enum StateChange { @@ -19,10 +19,15 @@ class HistoryServiceStateObserver: NSObject, HistoryServiceObserver { init(_ listener: @escaping (StateChange) -> Void) { self.listener = listener + } func historyServiceLoaded() { listener(.serviceLoaded) + + if !BraveServiceStateObserver.isServiceLoadStatePosted { + postServiceLoadedNotification() + } } func historyServiceBeingDeleted() { From cc2af9ed8edb31a4fa4846e8824c9ab84b650976 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 21 May 2021 13:58:35 -0400 Subject: [PATCH 11/43] Adding Sync Profile Toggles and logic --- BraveShared/BraveStrings.swift | 8 + Client/Application/ClientPreferences.swift | 11 +- Client/Application/Migration.swift | 2 +- .../Settings/SettingsViewController.swift | 2 +- .../BraveCore/BraveSyncAPI+Utilities.swift | 14 + .../SyncSettingsTableViewController.swift | 390 +++++++++++------- .../Sync/SyncWelcomeViewController.swift | 3 +- 7 files changed, 274 insertions(+), 156 deletions(-) diff --git a/BraveShared/BraveStrings.swift b/BraveShared/BraveStrings.swift index c4cd86e1aba..f72b62a8fb1 100644 --- a/BraveShared/BraveStrings.swift +++ b/BraveShared/BraveStrings.swift @@ -2194,6 +2194,14 @@ extension Strings { NSLocalizedString("sync.historyMigrationErrorMessage", tableName: "BraveShared", bundle: .braveShared, value: "Failed to migrate hitory. Please try again later.", comment: "Message for popup when the history migration fails") + public static let syncConfigurationInformationText = + NSLocalizedString("sync.syncConfigurationInformationText", tableName: "BraveShared", bundle: .braveShared, + value: "Manage what information you would like to sync between devices. These settings only affect this device.", + comment: "Information Text underneath the toggles for enable/disable different sync types for the device") + public static let syncSettingsTitle = + NSLocalizedString("sync.syncConfigurationInformationText", tableName: "BraveShared", bundle: .braveShared, + value: "Sync Settings", + comment: "Title for Sync Settings Toggle Header") } } diff --git a/Client/Application/ClientPreferences.swift b/Client/Application/ClientPreferences.swift index 1b5f907f1a1..e0bb01304e3 100644 --- a/Client/Application/ClientPreferences.swift +++ b/Client/Application/ClientPreferences.swift @@ -222,12 +222,19 @@ extension Preferences { } final class Chromium { + /// The boolean determine Bookmark Migration is finished on client side static let syncV2BookmarksMigrationCompleted = Option(key: "chromium.migration.bookmarks", default: false) + /// The boolean determine History Migration is finished on client side static let syncV2HistoryMigrationCompleted = Option(key: "chromium.migration.history", default: false) - + /// The count of how many time smigration is performed on client side - the value increases with every fail attempt and after 3 tries migration marked as successful static let syncV2ObjectMigrationCount = Option(key: "chromium.migration.bookmarks.count", default: 0) - + /// Whether the device is in sync chain static let syncEnabled = Option(key: "chromium.sync.enabled", default: false) + /// The sync type bookmarks enabled for the device in sync chain + static let syncBookmarksEnabled = Option(key: "chromium.sync.syncBookmarksEnabled", default: true) + /// The sync type history enabled for the device in sync chain + static let syncHistoryEnabled = Option(key: "chromium.sync.syncHistoryEnabled", default: false) + /// Node Id for last bookmark folder static let lastBookmarksFolderNodeId = Option(key: "chromium.last.bookmark.folder.node.id", default: nil) } diff --git a/Client/Application/Migration.swift b/Client/Application/Migration.swift index 1c90f34c275..52f8a7f31c5 100644 --- a/Client/Application/Migration.swift +++ b/Client/Application/Migration.swift @@ -57,7 +57,7 @@ class Migration { return } - BraveSyncProfileService.shared.userSelectedTypes = [.HISTORY, .BOOKMARKS] + BraveSyncAPI.shared.enableSyncTypes() } static func moveDatabaseToApplicationDirectory() { diff --git a/Client/Frontend/Settings/SettingsViewController.swift b/Client/Frontend/Settings/SettingsViewController.swift index f0b359a2b9f..1dddd9a3e0c 100644 --- a/Client/Frontend/Settings/SettingsViewController.swift +++ b/Client/Frontend/Settings/SettingsViewController.swift @@ -230,7 +230,7 @@ class SettingsViewController: TableViewController { } self.navigationController? - .pushViewController(SyncSettingsTableViewController(style: .grouped), animated: true) + .pushViewController(SyncSettingsTableViewController(), animated: true) } else { self.navigationController?.pushViewController(SyncWelcomeViewController(), animated: true) } diff --git a/Client/Frontend/Sync/BraveCore/BraveSyncAPI+Utilities.swift b/Client/Frontend/Sync/BraveCore/BraveSyncAPI+Utilities.swift index a6366cf3452..d015fcb4b75 100644 --- a/Client/Frontend/Sync/BraveCore/BraveSyncAPI+Utilities.swift +++ b/Client/Frontend/Sync/BraveCore/BraveSyncAPI+Utilities.swift @@ -21,6 +21,8 @@ extension BraveSyncAPI { func joinSyncGroup(codeWords: String) -> Bool { if self.setSyncCode(codeWords) { Preferences.Chromium.syncEnabled.value = true + enableSyncTypes() + return true } return false @@ -38,6 +40,18 @@ extension BraveSyncAPI { Preferences.Chromium.syncEnabled.value = false } + func enableSyncTypes() { + BraveSyncProfileService.shared.userSelectedTypes = [] + + if Preferences.Chromium.syncBookmarksEnabled.value { + BraveSyncProfileService.shared.userSelectedTypes.update(with: .BOOKMARKS) + } + + if Preferences.Chromium.syncHistoryEnabled.value { + BraveSyncProfileService.shared.userSelectedTypes.update(with: .HISTORY) + } + } + static func addServiceStateObserver(_ observer: @escaping () -> Void) -> AnyObject { let result = BraveSyncServiceListener(observer, onRemoved: { observer in serviceObservers.remove(observer) diff --git a/Client/Frontend/Sync/SyncSettingsTableViewController.swift b/Client/Frontend/Sync/SyncSettingsTableViewController.swift index 4e22adf453a..81f1dc72c67 100644 --- a/Client/Frontend/Sync/SyncSettingsTableViewController.swift +++ b/Client/Frontend/Sync/SyncSettingsTableViewController.swift @@ -10,20 +10,17 @@ import BraveRewards private let log = Logger.browserLogger class SyncSettingsTableViewController: UITableViewController { - private var syncDeviceObserver: AnyObject? - private var devices = [BraveSyncDevice]() - - private enum Sections: Int { case deviceList, buttons } - /// A different logic and UI is used depending on what device was selected to remove and if it is the only device - /// left in the Sync Chain. - enum DeviceRemovalType { case lastDeviceLeft, currentDevice, otherDevice } + // MARK: Lifecycle - /// After synchronization is completed, user needs to tap on `Done` to go back. - /// Standard navigation is disabled then. - var disableBackButton = false + init(showDoneButton: Bool = false) { + self.showDoneButton = showDoneButton + super.init(style: .grouped) + } - // MARK: - Lifecycle + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } override func viewDidLoad() { super.viewDidLoad() @@ -39,85 +36,141 @@ class SyncSettingsTableViewController: UITableViewController { self.updateDeviceList() - let text = UITextView().then { - $0.text = Strings.syncSettingsHeader - $0.textContainerInset = UIEdgeInsets(top: 16, left: 16, bottom: 0, right: 16) - $0.isEditable = false - $0.isSelectable = false - $0.textColor = .secondaryBraveLabel - $0.textAlignment = .center - $0.font = UIFont.systemFont(ofSize: 15) - $0.isScrollEnabled = false - $0.backgroundColor = .clear - } - - tableView.tableHeaderView = text + tableView.tableHeaderView = configureInformationView(with: Strings.syncSettingsHeader) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - tableView.tableHeaderView?.sizeToFit() - if disableBackButton { + if showDoneButton { navigationController?.interactivePopGestureRecognizer?.isEnabled = false - navigationItem.setHidesBackButton(true, animated: false) navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneTapped)) } } - // MARK: - Button actions. + // MARK: Private - @objc func doneTapped() { + private struct BraveSyncDevice: Codable { + let chromeVersion: String + let hasSharingInfo: Bool + let id: String + let guid: String + let isCurrentDevice: Bool + let supportsSelfDelete: Bool + let lastUpdatedTimestamp: TimeInterval + let name: String? + let os: String + let sendTabToSelfReceivingEnabled: Bool + let type: String + + func remove() { + // Devices other than `isCurrentDevice` can only be deleted if + // `supportsSelfDelete` is true. Attempting to delete another device + // from the sync chain that does not support it, will crash or + // have undefined behaviour as the other device won't know that + // it was deleted. + BraveSyncAPI.shared.removeDeviceFromSyncGroup(deviceGuid: self.guid) + } + } + + private var syncDeviceObserver: AnyObject? + private var devices = [BraveSyncDevice]() + + private enum Sections: Int { + case deviceList, deviceActions, syncTypes + } + + private enum SyncDataTypes: Int { + case bookmarks = 0, history + } + + /// A different logic and UI is used depending on what device was selected to remove and if it is the only device + /// left in the Sync Chain. + private enum DeviceRemovalType { + case lastDeviceLeft, currentDevice, otherDevice + } + + /// After synchronization is completed, user needs to tap on `Done` to go back. + /// Standard navigation is disabled then. + private var showDoneButton = false + + // MARK: Actions + + @objc private func doneTapped() { navigationController?.popToRootViewController(animated: true) } - private func addAnotherDeviceAction() { - let view = SyncSelectDeviceTypeViewController() - view.syncInitHandler = { title, type in - let view = SyncAddDeviceViewController(title: title, type: type) - view.doneHandler = { - self.navigationController?.popToViewController(self, animated: true) + private func presentAlertPopup(for type: DeviceRemovalType, device: BraveSyncDevice) { + var title: String? + var message: String? + var removeButtonName: String? + let deviceName = device.name ?? Strings.syncRemoveDeviceDefaultName + + switch type { + case .lastDeviceLeft: + title = String(format: Strings.syncRemoveLastDeviceTitle, deviceName) + message = Strings.syncRemoveLastDeviceMessage + removeButtonName = Strings.syncRemoveLastDeviceRemoveButtonName + case .currentDevice: + title = String(format: Strings.syncRemoveCurrentDeviceTitle, "\(deviceName) (\(Strings.syncThisDevice))") + message = Strings.syncRemoveCurrentDeviceMessage + removeButtonName = Strings.removeDevice + case .otherDevice: + title = String(format: Strings.syncRemoveOtherDeviceTitle, deviceName) + message = Strings.syncRemoveOtherDeviceMessage + removeButtonName = Strings.removeDevice + } + + guard let popupTitle = title, let popupMessage = message, let popupButtonName = removeButtonName else { fatalError() } + + let popup = AlertPopupView(imageView: nil, title: popupTitle, message: popupMessage) + let fontSize: CGFloat = 15 + + popup.addButton(title: Strings.cancelButtonTitle, fontSize: fontSize) { return .flyDown } + popup.addButton(title: popupButtonName, type: .destructive, fontSize: fontSize) { + switch type { + case .lastDeviceLeft, .currentDevice: + BraveSyncAPI.shared.leaveSyncGroup() + self.navigationController?.popToRootViewController(animated: true) + case .otherDevice: + device.remove() } - self.navigationController?.pushViewController(view, animated: true) + return .flyDown } - navigationController?.pushViewController(view, animated: true) + + popup.showWithType(showType: .flyUp) } - private func removeDeviceAction() { - let alert = UIAlertController(title: Strings.syncRemoveThisDeviceQuestion, message: Strings.syncRemoveThisDeviceQuestionDesc, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: Strings.cancelButtonTitle, style: .cancel, handler: nil)) - alert.addAction(UIAlertAction(title: Strings.removeDevice, style: .destructive) { action in - if !DeviceInfo.hasConnectivity() { - self.present(SyncAlerts.noConnection, animated: true) + @objc private func didToggleSyncType(_ toggle: UISwitch) { + switch toggle.tag { + case SyncDataTypes.bookmarks.rawValue: + Preferences.Chromium.syncBookmarksEnabled.value = toggle.isOn + case SyncDataTypes.history.rawValue: + Preferences.Chromium.syncHistoryEnabled.value = toggle.isOn + default: return - } - - BraveSyncAPI.shared.leaveSyncGroup() - self.navigationController?.popToRootViewController(animated: true) - }) + } - navigationController?.present(alert, animated: true, completion: nil) + BraveSyncAPI.shared.enableSyncTypes() } - - // MARK: - Table view methods. - +} + +// MARK: - UITableViewDelegate, UITableViewDataSource + +extension SyncSettingsTableViewController { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { defer { tableView.deselectRow(at: indexPath, animated: true) } - if indexPath.section == Sections.buttons.rawValue { - addAnotherDeviceAction() + if indexPath.section == Sections.deviceActions.rawValue { + addAnotherDevice() return } - let devices = self.devices - if devices.isEmpty { - return - } - - guard let device = devices[safe: indexPath.row] else { + guard !devices.isEmpty, let device = devices[safe: indexPath.row] else { return } @@ -142,7 +195,7 @@ class SyncSettingsTableViewController: UITableViewController { var alertType = DeviceRemovalType.otherDevice - if devices.count == 1 { + if self.devices.count == 1 { alertType = .lastDeviceLeft } else if device.isCurrentDevice { alertType = .currentDevice @@ -159,56 +212,21 @@ class SyncSettingsTableViewController: UITableViewController { present(actionSheet, animated: true) } - private func presentAlertPopup(for type: DeviceRemovalType, device: BraveSyncDevice) { - var title: String? - var message: String? - var removeButtonName: String? - let deviceName = device.name ?? Strings.syncRemoveDeviceDefaultName - - switch type { - case .lastDeviceLeft: - title = String(format: Strings.syncRemoveLastDeviceTitle, deviceName) - message = Strings.syncRemoveLastDeviceMessage - removeButtonName = Strings.syncRemoveLastDeviceRemoveButtonName - case .currentDevice: - title = String(format: Strings.syncRemoveCurrentDeviceTitle, "\(deviceName) (\(Strings.syncThisDevice))") - message = Strings.syncRemoveCurrentDeviceMessage - removeButtonName = Strings.removeDevice - case .otherDevice: - title = String(format: Strings.syncRemoveOtherDeviceTitle, deviceName) - message = Strings.syncRemoveOtherDeviceMessage - removeButtonName = Strings.removeDevice - } - - guard let popupTitle = title, let popupMessage = message, let popupButtonName = removeButtonName else { fatalError() } - - let popup = AlertPopupView(imageView: nil, title: popupTitle, message: popupMessage) - let fontSize: CGFloat = 15 - - popup.addButton(title: Strings.cancelButtonTitle, fontSize: fontSize) { return .flyDown } - popup.addButton(title: popupButtonName, type: .destructive, fontSize: fontSize) { - switch type { - case .lastDeviceLeft, .currentDevice: - BraveSyncAPI.shared.leaveSyncGroup() - self.navigationController?.popToRootViewController(animated: true) - case .otherDevice: - device.remove() - } - return .flyDown - } - - popup.showWithType(showType: .flyUp) - } - override func numberOfSections(in tableView: UITableView) -> Int { - return 2 + return 3 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - let deviceCount = devices.count - let buttonsCount = 1 - - return section == Sections.buttons.rawValue ? buttonsCount : deviceCount + switch section { + case Sections.deviceList.rawValue: + return devices.count + case Sections.deviceActions.rawValue: + return 1 + case Sections.syncTypes.rawValue: + return 2 + default: + return 0 + } } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { @@ -218,6 +236,35 @@ class SyncSettingsTableViewController: UITableViewController { return cell } + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + switch section { + case Sections.deviceList.rawValue: + return Strings.devices + case Sections.syncTypes.rawValue: + return Strings.Sync.syncSettingsTitle + default: + return nil + } + } + + override func tableView(_ tableView: UITableView, viewForFooterInSection sectionIndex: Int) -> UIView? { + switch sectionIndex { + case Sections.syncTypes.rawValue: + return configureInformationView(with: Strings.Sync.syncConfigurationInformationText) + default: + return nil + } + } + + override func tableView(_ tableView: UITableView, heightForFooterInSection sectionIndex: Int) -> CGFloat { + switch sectionIndex { + case Sections.syncTypes.rawValue: + return UITableView.automaticDimension + default: + return 0 + } + } + private func configureCell(_ cell: UITableViewCell, atIndexPath indexPath: IndexPath) { if devices.isEmpty { log.error("No sync devices to configure.") @@ -225,21 +272,23 @@ class SyncSettingsTableViewController: UITableViewController { } switch indexPath.section { - case Sections.deviceList.rawValue: - guard let device = devices[safe: indexPath.row] else { - log.error("Invalid device to configure.") - return - } - - guard let name = device.name else { break } - let deviceName = device.isCurrentDevice ? "\(name) (\(Strings.syncThisDevice))" : name - - cell.textLabel?.text = deviceName - cell.textLabel?.textColor = .braveLabel - case Sections.buttons.rawValue: - configureButtonCell(cell) - default: - log.error("Section index out of bounds.") + case Sections.deviceList.rawValue: + guard let device = devices[safe: indexPath.row] else { + log.error("Invalid device to configure.") + return + } + + guard let name = device.name else { break } + let deviceName = device.isCurrentDevice ? "\(name) (\(Strings.syncThisDevice))" : name + + cell.textLabel?.text = deviceName + cell.textLabel?.textColor = .braveLabel + case Sections.deviceActions.rawValue: + configureButtonCell(cell) + case Sections.syncTypes.rawValue: + configureToggleCell(cell, for: SyncDataTypes(rawValue: indexPath.row) ?? .bookmarks) + default: + log.error("Section index out of bounds.") } } @@ -258,25 +307,57 @@ class SyncSettingsTableViewController: UITableViewController { } } - override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + private func configureToggleCell(_ cell: UITableViewCell, for syncType: SyncDataTypes) { + let toggle = UISwitch().then { + $0.addTarget(self, action: #selector(didToggleSyncType), for: .valueChanged) + $0.isOn = isOn(syncType: syncType) + $0.tag = syncType.rawValue + } - switch section { - case Sections.deviceList.rawValue: - return Strings.devices.uppercased() - default: - return nil + cell.do { + $0.textLabel?.text = syncType == .bookmarks ? Strings.bookmarks : Strings.historyMenuItem + $0.accessoryView = toggle + $0.selectionStyle = .none + } + + cell.separatorInset = .zero + + func isOn(syncType: SyncDataTypes) -> Bool { + switch syncType { + case .bookmarks: + return Preferences.Chromium.syncBookmarksEnabled.value + case .history: + return Preferences.Chromium.syncHistoryEnabled.value + } + } + } + + private func configureInformationView(with info: String) -> UITextView { + return UITextView().then { + $0.text = info + $0.textContainerInset = UIEdgeInsets(top: 16, left: 16, bottom: 0, right: 16) + $0.isEditable = false + $0.isSelectable = false + $0.textColor = .secondaryBraveLabel + $0.textAlignment = .center + $0.font = UIFont.systemFont(ofSize: 15) + $0.isScrollEnabled = false + $0.backgroundColor = .clear } } } +// MARK: - Sync Device Functionality + extension SyncSettingsTableViewController { + private func updateDeviceList() { if let json = BraveSyncAPI.shared.getDeviceListJSON(), let data = json.data(using: .utf8) { do { let devices = try JSONDecoder().decode([BraveSyncDevice].self, from: data) self.devices = devices - if self.devices.count <= 0 { + if devices.count <= 0 { // Technically we shouldn't be calling this function.. // If Desktop deletes an iOS device from the chain, we're already removed.. // We should be just updating our UI and calling @@ -296,27 +377,36 @@ extension SyncSettingsTableViewController { log.error("Something went wrong while retrieving Sync Devices..") } } -} - -private struct BraveSyncDevice: Codable { - let chromeVersion: String - let hasSharingInfo: Bool - let id: String - let guid: String - let isCurrentDevice: Bool - let supportsSelfDelete: Bool - let lastUpdatedTimestamp: TimeInterval - let name: String? - let os: String - let sendTabToSelfReceivingEnabled: Bool - let type: String - func remove() { - // Devices other than `isCurrentDevice` can only be deleted if - // `supportsSelfDelete` is true. Attempting to delete another device - // from the sync chain that does not support it, will crash or - // have undefined behaviour as the other device won't know that - // it was deleted. - BraveSyncAPI.shared.removeDeviceFromSyncGroup(deviceGuid: self.guid) + private func addAnotherDevice() { + let view = SyncSelectDeviceTypeViewController() + + view.syncInitHandler = { title, type in + let view = SyncAddDeviceViewController(title: title, type: type) + view.doneHandler = { + self.navigationController?.popToViewController(self, animated: true) + } + self.navigationController?.pushViewController(view, animated: true) + } + navigationController?.pushViewController(view, animated: true) + } + + private func removeDeviceAction() { + let alert = UIAlertController(title: Strings.syncRemoveThisDeviceQuestion, + message: Strings.syncRemoveThisDeviceQuestionDesc, + preferredStyle: .alert) + alert.addAction(UIAlertAction(title: Strings.cancelButtonTitle, style: .cancel, handler: nil)) + alert.addAction(UIAlertAction(title: Strings.removeDevice, style: .destructive) { action in + if !DeviceInfo.hasConnectivity() { + self.present(SyncAlerts.noConnection, animated: true) + return + } + + BraveSyncAPI.shared.leaveSyncGroup() + self.navigationController?.popToRootViewController(animated: true) + }) + + navigationController?.present(alert, animated: true, completion: nil) } } + diff --git a/Client/Frontend/Sync/SyncWelcomeViewController.swift b/Client/Frontend/Sync/SyncWelcomeViewController.swift index b61f1b81605..4175ba05285 100644 --- a/Client/Frontend/Sync/SyncWelcomeViewController.swift +++ b/Client/Frontend/Sync/SyncWelcomeViewController.swift @@ -239,8 +239,7 @@ class SyncWelcomeViewController: SyncViewController { return } - let syncSettingsVC = SyncSettingsTableViewController(style: .grouped) - syncSettingsVC.disableBackButton = true + let syncSettingsVC = SyncSettingsTableViewController(showDoneButton: true) navigationController?.pushViewController(syncSettingsVC, animated: true) } } From 061b2e099e47a9dc4f866e902af27b782aef0c18 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 21 May 2021 16:34:28 -0400 Subject: [PATCH 12/43] Adding Clear All Functionality to History View Controller --- BraveShared/BraveStrings.swift | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/BraveShared/BraveStrings.swift b/BraveShared/BraveStrings.swift index f72b62a8fb1..c307cbae883 100644 --- a/BraveShared/BraveStrings.swift +++ b/BraveShared/BraveStrings.swift @@ -2206,8 +2206,25 @@ extension Strings { } extension Strings { - public struct BraveNews { - public static let braveNews = NSLocalizedString( + public struct History { + public static let historyClearAlertTitle = + NSLocalizedString("history.historyClearAlertTitle", tableName: "BraveShared", bundle: .braveShared, + value: "Clear Browsing History", + comment: "Title for Clear All History Alert Title") + public static let historyClearAlertDescription = + NSLocalizedString("history.historyClearAlertDescription", tableName: "BraveShared", bundle: .braveShared, + value: "This will clear all browsing history.", + comment: "Description for Clear All History Alert Description") + public static let historyClearActionTitle = + NSLocalizedString("history.historyClearActionTitle", tableName: "BraveShared", bundle: .braveShared, + value: "Clear History", + comment: "Title for History Clear All Action") + } +} + +extension Strings { + public struct BraveToday { + public static let braveToday = NSLocalizedString( "today.braveToday", bundle: .braveShared, value: "Brave News", From 4da258201ec8ff77f7d6276fee25ec936a71b4a4 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 21 May 2021 16:38:23 -0400 Subject: [PATCH 13/43] Removing Local Resolved File For Brave Core --- BraveCore/Local.resolved | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 BraveCore/Local.resolved diff --git a/BraveCore/Local.resolved b/BraveCore/Local.resolved deleted file mode 100644 index 6fd8b943817..00000000000 --- a/BraveCore/Local.resolved +++ /dev/null @@ -1,8 +0,0 @@ -REMINDER: Your local brave-core-ios dependency has been overwritten in node_modules. Re-run bootstrap.sh when you are done testing. - -build: Debug -brave-browser: 1.23.x (77c504a6b4e661e9140d3a7d2a63706b8b659981) -brave-core: ios/sync/history (90f24d51b381878a4c967cff1d5245481e0f6fd7) - latest tag: v1.23.76 - -DO NOT COMMIT THIS FILE From bf80b0aa00ed2b5d5a3c19074186c25d340065e8 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 25 May 2021 15:34:57 -0400 Subject: [PATCH 14/43] Adding State Empty to to overlay in History Controller --- BraveShared/BraveStrings.swift | 5 +++++ .../Menu/emptyHistory.imageset/Contents.json | 21 ++++++++++++++++++ .../emptyHistory.imageset/historyEmpty@2x.png | Bin 0 -> 5189 bytes .../Menu/HistoryViewController.swift | 1 + 4 files changed, 27 insertions(+) create mode 100644 Client/Assets/Images.xcassets/Menu/emptyHistory.imageset/Contents.json create mode 100644 Client/Assets/Images.xcassets/Menu/emptyHistory.imageset/historyEmpty@2x.png diff --git a/BraveShared/BraveStrings.swift b/BraveShared/BraveStrings.swift index c307cbae883..7aba9e5bf8b 100644 --- a/BraveShared/BraveStrings.swift +++ b/BraveShared/BraveStrings.swift @@ -2219,6 +2219,11 @@ extension Strings { NSLocalizedString("history.historyClearActionTitle", tableName: "BraveShared", bundle: .braveShared, value: "Clear History", comment: "Title for History Clear All Action") + + public static let historyEmptyStateTitle = + NSLocalizedString("history.historyEmptyStateTitle", tableName: "BraveShared", bundle: .braveShared, + value: "History will show up here.", + comment: "Title which is displayed when History screen is empty.") } } diff --git a/Client/Assets/Images.xcassets/Menu/emptyHistory.imageset/Contents.json b/Client/Assets/Images.xcassets/Menu/emptyHistory.imageset/Contents.json new file mode 100644 index 00000000000..d6c7cc6abad --- /dev/null +++ b/Client/Assets/Images.xcassets/Menu/emptyHistory.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "historyEmpty@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Client/Assets/Images.xcassets/Menu/emptyHistory.imageset/historyEmpty@2x.png b/Client/Assets/Images.xcassets/Menu/emptyHistory.imageset/historyEmpty@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..329ea8f1a8388d48aca7778e09dff86cdd804ef8 GIT binary patch literal 5189 zcmV-L6uRq)P) zdvH`$p2xqxbG!56AwCdS1rZqpM1|D>El0OiAi05by5rt-`xtfCMYkMxR~gW$S|cxVb;1xE!f#K$1wYerxd44RO1?)mK>-M9gg^ts)) zUrB$etg^d*=bT^e`El<#=l&i98+be(SH;O^+{w&K0L%dRFo9kK*e>q-L6 z1!x|?7XcWRq2ay-V< z4(K%~x~`W>_vovI5Y+${0ysaD<0uV2smaI7BCabzpATKVe+-%~h*nxmG9{E)}7} zF>NA&hn#!>0MnebHR?yTKQN6!OTf69nNN4J?+h^(zzra};q?87_Ur!oXQjnYx3`+R zbFJ85C>emXVr80^T$I2iX=?;fwcnU8B`sw}CBVv$sr-UY2VOMo;d!%XwuV9>nQO&>xNN4qX6$15h_JdI5k4B>;bR?;9U~p4@B0-VD0lGhswT8 zwomtXZY`@grE`L0Z6dRFt{|RDj9Cm^3}6auoSi6A!i44JF>#&lHh`qYGx%sP9J4+bICyD=F>Hpic{+mxNMbG7s zxQYo25H|{^{+20Vu~GL0p6WhSzC2q8N=nKvthsKwrn%lz5DiDdjsD}mT;vbTl0X9( z7ueQtVEP#70ONU=CD*N6XMW*OzqVN54W6kH*ASr&z_kE0hq~S+Em7aT_IK|()Zd_F z+yJV4^*0gdX#f?eD0mzn65$yUlh5U9(g$OKH+ZH?$eRFK0${2GU3Nj@_DE~vY6ton zl#Cfb;`sOp0C%UOAOHqvla$tq_Exh!{yBdMg+gNM_FW5zXek`n-4M~rxff4gmZ@`t zj2M8|>m3slk=BOoY4npbs_Ftigv8GXs7}?3ceJnO}-?ee?yOJ z)^MGC0B8?4HFdk>bON3NkjgXtJOaN|eklQ!>Nv)i#xzU$*f148&{w>`2c{# zwWtPg&|XWvBqqum48utI1TxzO@CjJ{sJ*3WQp# zRrdyG=URzuv1zUOsUR$dz1_iGx-X#o7E;Lo1d06Fu8}-D*D7R_w&up2lDQs$YEUWx zc)F&hM#=v|$pDUs*gm9ocI`OCBBQZ~`AB^6%lFx6GT9OpAr(O-1Lz2c4*__|h60)5 zlToEsLHY)yOC;R10>BHZ@=Ul#uQg^SlT%*8k_jmrK%}){J4vpB{gWyu_!>+%L|e?}9E_bew6#5VkU_UV{c&7bRa;*$snGT2`O2VeJd==Rz+#==zOg zQP#Ih-Lr`Ok#JLZpkE5@93U-p!x%3an{eXf1HdfJ<=S+u-+yYh^|DJOvbqzJeyZMr z9>5^~*hiEBppSkE;LJgPXPi|kOYCg7az>=3p$P<4N18d+eq;VXKa4B`04+`?!GuNG z(8K|lB;5-|p9(2y=|JC)ECXQtS#lAckPTIwV0}x&HUKRuvP4u_`J_(&%rF|8j&G!0;m;HAQNE5=^&vJf34B!ixql43N@Fdg7O0eA(FX z$As$@4PY3M2%7y+MV2&C-~V&b0EPz)@UImmy}GWK9{pG}fMJ5x$EyLT9A%F|>DX(I zekdBiFk#&~^9uqx6ve+^2NVrp7$F(YD~f*aGFCKzVT8+)>!5ZfFio$kI~yn(z_22b zH%ZB3iY)CaplATY5v4;RCUF^1G=Sj;^DD`P05E6&VX3+qKCA>>X3Yc0nfZ>QFrKn;enp8A^VF+td zHFjfS(Ex@ctSJ_=qzT`9hg5ovDovxi7&IFU3yfEZ>B;r24R2&h&mx)O$f2??%f}^; z;$!C11OQa~f*~P9gqap4f(<5t5M;rxRo4doD$@#QgUZ_Al>jMZ&!F-uU(l0rg)&H@ z*hE({IU+tuRQUsS4F2aqWL!*my2^X~Mb4_2UG&=EeS)|H@q*FGC?)V_-B*8ahSkb2 z{7q5`&=^5X_au>XlaN1gNUN-)`-96s{0QuwdJ2FZ)obgQWlFEiLrI?j1e6MZFHz`i zt^*on9la)S8JKP5%sB?4N2>hBQrk2F>B|l3DOsWnbq>n2|gjYKt3ahRD&e) z5PGH0E&ndn)&lYeilTd61ngE+Drwfqd}2d$<4)ZdSda9omja;u%>1<@N)0s%fdTp) zB+c%F`+k#7$~ppFpt1mBDfhTQq~tyXpy0A}YnpbqWmz7iUbwo8rFB)b)wGkhKj$#i zb`O@@{hpXNd&b95cy$P1N~K|(lAdbWW!($U{ecO$BDF-<5-e{iw8>ATxto$qj)8B- ziP#K~#UOqjL*ES;#LWO^N1Gc{Dd?DcB(72sV?nP2fC~VK zX)6<}tU3owHdqL>z3|)~0EX@hoX3P(Vq5}HJk=`mpBVhQlpNl$*8DiPnx+R67N`lz ztw7>dq1V-&4e3@n4`8iNPE16h7RfUfFE-AyT;emRo+D3L@4429>W;Tpq1(^_~F5R88mP*5^idN`d#2GDzhF^SExujRK&!i z7^?o^vAi*F_RK*K_=bv{WoEu#RVik^tI#uR6au>6xQ2nhRh5@g{!=Iv8q^6U>EccI z1)=~{PyId>F>Q8R+j9q16)d8T&*vN0gVG%UlwvfPIT~$g(ua~s9y`x+Dbz}l0Kg>a zwtj`;t{@XoFG_z6#mNWID+Mi2CY1E;(e4j+9hi3htT7;{I)u*r!So9b?|%Q?*A(T8 zC{XPWEM?$sRe55ph=v=I`VZzCx-YPh+18$aPgjXl z+Qlguz}mHIy8zq)#X`jZG(psqUVM8I07zWJ2B?>`l_0sK!!(uL;Fa^|Bn}dOsVWcP zWR0<|rpB0LqfL>1RM*v=qcPS2IN3(Cry|Yfi>ku55-5#!%lklh*G7|b`ZTdYH;nOi z#wh~mhA|$NI|}th9{}v?K2)A`;nyEq24I?Iw*Z1r3ne?s`G|?lMI%s0H;nO!iOo!y zZlhV3v_yS>ZyyzGr%-EaZrsV>J8U+)kbA|J>bknZ$}x}wYHEy0h>4d0TxhGI#O>{C ze`n|J3_yKhaSXfPfA^hfGcG&{fN~N=BAf=+{8MJk+Vs);?<#p6jWibe1G7N15x{wN z+7Z#pNK4}rsf?L&62(z2YdI8M$@_7R#@M3!0%{&CBZ$h{`uQ4T3+z4fK}2nHFP@%q zO53zf?7Uv@n3$+|Nip4Qe=H{48*Oe>^*b2OP_;jBPhy{M_m2Elw_E;&>XvW7!BcH` zl!g8upRRH5tFU?7N({cH1U8Cf}c!O zWl4pP7&PCh$praXbFy+$PqZ7IO>k>)if zqLrgu)^gJ{Er;|ww*O3Y+8^B;xDf)Ykb17Z{_G~gs+dKqH?}tX(SiOPBc7gxZcIc@ zPjjHlE(YHb4LAMPfxZSME3R9WHP>GtG}#2escfSbfX&QUV==AGl`$+{Y@F4niN%8O zmkfB2NV=6agm)ojeWb-yP2!oxP+7v`xwWi(T=(Mu?nHWZe2#|!yiJUa5ZKa#-q$ua zH-F_||KC$-7^jF{x+0M-Z$5xIaP}H9fM1Sw%lk~zOkVlX0kZDAsr!v$Yz-$ z3}6odZ!=-1WZF$+eJsfOtn2Hs`;xsb^>}VAD;sy@43Kp;S>l{{l5CoZc&gkf$lNvC z3*e5yB6u=IPP}(LhB3OLS3JOke*m&xkm@^tI~jBY9IuxYFN($G0G$M9)+%=BBgRTi zc7+nIcUdK;?%NCffmuS*<3wDQOFeQ(J6JBw#zR;5@+nM?P zXiJl77=Fgc3j+Y+=LXw$?D7KiGYnrt*beZ6iMY$WsA-fp2GE~`!^lzq3*hXIAr~++ zwF_abNQB+z#l#;aFAd-*m0n}2(6l?ixEbIAD+5RSL3oxe>zRD6Igr-|aFk1KzukTM zzC%?Y3IbRRAYXG490sA4E!lLW^T7Ia%D!Zaf-r#ocs#e3m5%N42q70Co*m1HW7l-} z5I{SC2zokSj6@p38(;1dPtma9v=$1H$i#X)9~J zTaISkE>sHM0FK8n4DFDVQ?!_S1__=5U^0l$0*f;MJ{63UK|BheawN{~IbK1%hroxK z>6>^pRo(~SGiLsjfZZV4HE;Hej|<>!q%Hmrg{T`BAVY9~00000NkvXXu0mjfNRgms literal 0 HcmV?d00001 diff --git a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift index 4a3c5905b36..3f055efa5e3 100644 --- a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift +++ b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift @@ -230,3 +230,4 @@ extension HistoryViewController: NSFetchedResultsControllerDelegate { updateEmptyPanelState() } } + From 2e6d4546eb08704e201675e8f35c153c59b12c25 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 25 May 2021 17:52:25 -0400 Subject: [PATCH 15/43] Error while fetching details is fixed --- .../Sync/BraveCore/History/HistoryFetchers.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift index a3311f67eb4..b5e96fba3c3 100644 --- a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift +++ b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift @@ -79,7 +79,7 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { } var sectionCount: Int { - sectionDetails.elements.filter { $0.value > 0 }.count + return sectionDetails.elements.filter { $0.value > 0 }.count } func performFetch(_ completion: @escaping () -> Void) { @@ -114,12 +114,13 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { } func objectCount(for section: Int) -> Int { - return sectionDetails.elements[safe: section]?.value ?? 0 + let filteredDetails = sectionDetails.elements.filter { $0.value > 0 } + return filteredDetails[safe: section]?.value ?? 0 } func titleHeader(for section: Int) -> String { - return sectionDetails.elements[safe: section]?.key.title ?? "" - + let filteredDetails = sectionDetails.elements.filter { $0.value > 0 } + return filteredDetails[safe: section]?.key.title ?? "" } // MARK: Private From eeb8f41faefa57d8795bd27cb656fad8d292c7b3 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Thu, 27 May 2021 12:12:48 -0400 Subject: [PATCH 16/43] Adding Visit Type Back to Browser --- Client.xcodeproj/project.pbxproj | 4 ++ .../Browser/BrowserViewController.swift | 41 ++++++++++--------- .../BrowserViewController+ReaderMode.swift | 4 ++ ...rowserViewController+ToolbarDelegate.swift | 9 ++-- ...Controller+UIDropInteractionDelegate.swift | 2 +- .../Bookmarks/BookmarksViewController.swift | 3 +- .../Toolbars/ToolbarUrlActionsDelegate.swift | 2 +- Client/Frontend/Browser/VisitType.swift | 32 +++++++++++++++ 8 files changed, 71 insertions(+), 26 deletions(-) create mode 100644 Client/Frontend/Browser/VisitType.swift diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index 7ea1c7ea6ba..9526ad2d1a4 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -450,6 +450,7 @@ 2F676FAD260BA4860048A1DB /* blocking-summary.json in Resources */ = {isa = PBXBuildFile; fileRef = 2F676FAC260BA4860048A1DB /* blocking-summary.json */; }; 2F6931B7260CFB3700ECEB38 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F6931B6260CFB3700ECEB38 /* IntentHandler.swift */; }; 2F6931BB260CFB3700ECEB38 /* BrowserIntents.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 2F6931B4260CFB3700ECEB38 /* BrowserIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 2F5893D6265FEF7E002323D9 /* VisitType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F5893D5265FEF7E002323D9 /* VisitType.swift */; }; 2F697F7E1A9FD22D009E03AE /* SearchEnginesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F697F7D1A9FD22D009E03AE /* SearchEnginesTests.swift */; }; 2F91AFD325FFA830002DBC4A /* ActivityShortcutManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F91AFD225FFA830002DBC4A /* ActivityShortcutManager.swift */; }; 2F9311D52665883400C6B74D /* DataSaved.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F9311D42665883400C6B74D /* DataSaved.swift */; }; @@ -1953,6 +1954,7 @@ 2F69320D260D048400ECEB38 /* BrowserIntentsRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = BrowserIntentsRelease.entitlements; sourceTree = ""; }; 2F69320E260D056100ECEB38 /* BrowserIntentsBeta.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = BrowserIntentsBeta.entitlements; sourceTree = ""; }; 2F693223260D218900ECEB38 /* CustomIntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomIntentHandler.swift; sourceTree = ""; }; + 2F5893D5265FEF7E002323D9 /* VisitType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisitType.swift; sourceTree = ""; }; 2F697F7D1A9FD22D009E03AE /* SearchEnginesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchEnginesTests.swift; sourceTree = ""; }; 2F84BCF8267BE0A100850801 /* Model13.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model13.xcdatamodel; sourceTree = ""; }; 2F91AFD225FFA830002DBC4A /* ActivityShortcutManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityShortcutManager.swift; sourceTree = ""; }; @@ -5159,6 +5161,7 @@ 4452CAEF255412800053EFE6 /* DefaultBrowserIntroCalloutViewController.swift */, 0A0A5ED025B1F080007B3E74 /* DefaultBrowserIntroManager.swift */, 0AE50869261C6F2E0099C6A3 /* BraveSearchHelper.swift */, + 2F5893D5265FEF7E002323D9 /* VisitType.swift */, ); indentWidth = 4; path = Browser; @@ -7131,6 +7134,7 @@ 27FD2CAD2146C31C00A5A779 /* AddToFavoritesActivity.swift in Sources */, 4422D4E121BFFB7600BF1855 /* filter_block.cc in Sources */, 0A8C69BE225E350300988715 /* IndentedImageTableViewCell.swift in Sources */, + 2F5893D6265FEF7E002323D9 /* VisitType.swift in Sources */, 0AE5C69124F0059D004CBC9B /* OnboardingPrivacyConsentViewController.swift in Sources */, 5E096180252B63F200F3AFBB /* BraveSyncAPI+Utilities.swift in Sources */, 5E5E6E3A25BA03510035B6A0 /* PlaylistViewController.swift in Sources */, diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index 1fc254e0156..7336dd9ebb0 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -123,6 +123,7 @@ class BrowserViewController: UIViewController { // Tracking navigation items to record history types. // TODO: weak references? var ignoredNavigation = Set() + var typedNavigation = [WKNavigation: VisitType]() var navigationToolbar: ToolbarProtocol { return toolbar ?? topToolbar } @@ -1217,13 +1218,11 @@ class BrowserViewController: UIViewController { } } - func finishEditingAndSubmit(_ url: URL, isBookmark: Bool) { - if url.isBookmarklet, isBookmark { + func finishEditingAndSubmit(_ url: URL, visitType: VisitType) { + if url.isBookmarklet { topToolbar.leaveOverlayMode() - guard let tab = tabManager.selectedTab, - let webView = tab.webView, - let code = url.bookmarkletCodeComponent else { + guard let tab = tabManager.selectedTab else { return } @@ -1231,9 +1230,13 @@ class BrowserViewController: UIViewController { // Disable any sort of privileged execution contexts // IE: The user must explicitly tap a bookmark they have saved. // Block all other contexts such as redirects, downloads, embed, linked, etc.. - webView.evaluateSafeJavaScript(functionName: code, sandboxed: false, asFunction: false) { _, error in - if let error = error { - log.error(error) + if visitType == .bookmark { + if let webView = tab.webView, let code = url.bookmarkletCodeComponent { + webView.evaluateSafeJavaScript(functionName: code, sandboxed: false, asFunction: false) { _, error in + if let error = error { + log.error(error) + } + } } } } else { @@ -1889,8 +1892,8 @@ extension BrowserViewController: ClipboardBarDisplayHandlerDelegate { extension BrowserViewController: QRCodeViewControllerDelegate { func didScanQRCodeWithURL(_ url: URL) { popToBVC() - finishEditingAndSubmit(url, isBookmark: false) - + finishEditingAndSubmit(url, visitType: .typed) + if !url.isBookmarklet && !PrivateBrowsingManager.shared.isPrivateBrowsing { RecentSearch.addItem(type: .qrCode, text: nil, websiteUrl: url.absoluteString) } @@ -2072,7 +2075,7 @@ extension BrowserViewController: SearchViewControllerDelegate { } func searchViewController(_ searchViewController: SearchViewController, didSelectURL url: URL) { - finishEditingAndSubmit(url, isBookmark: false) + finishEditingAndSubmit(url, visitType: .typed) } func searchViewController(_ searchViewController: SearchViewController, didLongPressSuggestion suggestion: String) { @@ -2645,15 +2648,15 @@ extension BrowserViewController: ToolbarUrlActionsDelegate { func openInNewTab(_ url: URL, isPrivate: Bool) { topToolbar.leaveOverlayMode() - select(url, isBookmark: false, action: .openInNewTab(isPrivate: isPrivate)) + select(url, visitType: .unknown, action: .openInNewTab(isPrivate: isPrivate)) } func copy(_ url: URL) { - select(url, isBookmark: false, action: .copy) + select(url, visitType: .unknown, action: .copy) } func share(_ url: URL) { - select(url, isBookmark: false, action: .share) + select(url, visitType: .unknown, action: .share) } func batchOpen(_ urls: [URL]) { @@ -2661,14 +2664,14 @@ extension BrowserViewController: ToolbarUrlActionsDelegate { self.tabManager.addTabsForURLs(urls, zombie: false, isPrivate: tabIsPrivate) } - func select(url: URL, isBookmark: Bool) { - select(url, isBookmark: isBookmark, action: .openInCurrentTab) + func select(url: URL, visitType: VisitType) { + select(url, visitType: visitType, action: .openInCurrentTab) } - private func select(_ url: URL, isBookmark: Bool, action: ToolbarURLAction) { + private func select(_ url: URL, visitType: VisitType, action: ToolbarURLAction) { switch action { case .openInCurrentTab: - finishEditingAndSubmit(url, isBookmark: isBookmark) + finishEditingAndSubmit(url, visitType: visitType) case .openInNewTab(let isPrivate): let tab = tabManager.addTab(PrivilegedRequest(url: url) as URLRequest, afterTab: tabManager.selectedTab, isPrivate: isPrivate) if isPrivate && !PrivateBrowsingManager.shared.isPrivateBrowsing { @@ -2706,7 +2709,7 @@ extension BrowserViewController: NewTabPageDelegate { if inNewTab { tabManager.addTabAndSelect(isPrivate: isPrivate) } - processAddressBar(text: input) + processAddressBar(text: input, visitType: .bookmark) } func handleFavoriteAction(favorite: Favorite, action: BookmarksAction) { diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift index 884eee6260c..e22bbb3f098 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift @@ -191,4 +191,8 @@ extension BrowserViewController { func ignoreNavigationInTab(_ tab: Tab, navigation: WKNavigation) { self.ignoredNavigation.insert(navigation) } + + func recordNavigationInTab(_ tab: Tab, navigation: WKNavigation, visitType: VisitType) { + self.typedNavigation[navigation] = visitType + } } diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift index 11705e5b5d3..b517d6cdde0 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift @@ -159,13 +159,14 @@ extension BrowserViewController: TopToolbarDelegate { } func topToolbar(_ topToolbar: TopToolbarView, didSubmitText text: String) { - processAddressBar(text: text) + processAddressBar(text: text, visitType: nil) } - func processAddressBar(text: String) { + func processAddressBar(text: String, visitType: VisitType?) { if let fixupURL = URIFixup.getURL(text) { // The user entered a URL, so use it. - finishEditingAndSubmit(fixupURL, isBookmark: false) + finishEditingAndSubmit(fixupURL, visitType: visitType ?? .typed) + return } @@ -182,7 +183,7 @@ extension BrowserViewController: TopToolbarDelegate { if let searchURL = engine.searchURLForQuery(text) { // We couldn't find a matching search keyword, so do a search query. - finishEditingAndSubmit(searchURL, isBookmark: false) + finishEditingAndSubmit(searchURL, visitType: .typed) } else { // We still don't have a valid URL, so something is broken. Give up. print("Error handling URL entry: \"\(text)\".") diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+UIDropInteractionDelegate.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+UIDropInteractionDelegate.swift index 558eca25684..a2ceb91040c 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+UIDropInteractionDelegate.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+UIDropInteractionDelegate.swift @@ -26,7 +26,7 @@ extension BrowserViewController: UIDropInteractionDelegate { return } - self.finishEditingAndSubmit(url, isBookmark: false) + self.finishEditingAndSubmit(url, visitType: .typed) } } } diff --git a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarksViewController.swift b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarksViewController.swift index bed3ff9fd56..eeda4cbc60d 100644 --- a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarksViewController.swift +++ b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/BookmarksViewController.swift @@ -441,7 +441,8 @@ class BookmarksViewController: SiteTableViewController, ToolbarUrlActionsProtoco if !self.isPrivateBrowsing { ActivityShortcutManager.shared.donateCustomIntent(for: .openBookmarks, with: url.absoluteString) } - self.toolbarUrlActionsDelegate?.select(url: url, isBookmark: true) + + self.toolbarUrlActionsDelegate?.select(url: url, visitType: .bookmark) } if presentingViewController is MenuViewController { diff --git a/Client/Frontend/Browser/Toolbars/ToolbarUrlActionsDelegate.swift b/Client/Frontend/Browser/Toolbars/ToolbarUrlActionsDelegate.swift index a43ac87bdef..20ba86f7c14 100644 --- a/Client/Frontend/Browser/Toolbars/ToolbarUrlActionsDelegate.swift +++ b/Client/Frontend/Browser/Toolbars/ToolbarUrlActionsDelegate.swift @@ -10,5 +10,5 @@ protocol ToolbarUrlActionsDelegate: AnyObject { func copy(_ url: URL) func share(_ url: URL) func batchOpen(_ urls: [URL]) - func select(url: URL, isBookmark: Bool) + func select(url: URL, visitType: VisitType) } diff --git a/Client/Frontend/Browser/VisitType.swift b/Client/Frontend/Browser/VisitType.swift new file mode 100644 index 00000000000..5b02a29f3e1 --- /dev/null +++ b/Client/Frontend/Browser/VisitType.swift @@ -0,0 +1,32 @@ +// Copyright 2021 The Brave Authors. All rights reserved. +// 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 + +// These are taken from the Places docs +// http://mxr.mozilla.org/mozilla-central/source/toolkit/components/places/nsINavHistoryService.idl#1187 +enum VisitType: Int { + case unknown = 0 + + /** + * This transition type means the user followed a link and got a new toplevel + * window. + */ + case link = 1 + + /** + * This transition type means that the user typed the page's URL in the + * URL bar or selected it from URL bar autocomplete results, clicked on + * it from a history query (from the History sidebar, History menu, + * or history query in the personal toolbar or Places organizer). + */ + case typed = 2 + + case bookmark = 3 + case embed = 4 + case permanentRedirect = 5 + case temporaryRedirect = 6 + case download = 7 + case framedLink = 8 +} From fd0ff779426ffb5597f9032466647201bc7f53a1 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Thu, 27 May 2021 15:08:48 -0400 Subject: [PATCH 17/43] Adding distinction between typed and local history add --- .../Browser/BrowserViewController.swift | 17 ++++++++++++++--- .../BrowserViewController+ReaderMode.swift | 8 ++++++-- .../BrowserViewController+ToolbarDelegate.swift | 9 ++++++--- .../Sync/BraveCore/History/Historyv2.swift | 5 +++++ 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index 7336dd9ebb0..f678f1ac3e6 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -123,7 +123,7 @@ class BrowserViewController: UIViewController { // Tracking navigation items to record history types. // TODO: weak references? var ignoredNavigation = Set() - var typedNavigation = [WKNavigation: VisitType]() + var typedNavigation = [URL: VisitType]() var navigationToolbar: ToolbarProtocol { return toolbar ?? topToolbar } @@ -1247,7 +1247,11 @@ class BrowserViewController: UIViewController { return } - tab.loadRequest(URLRequest(url: url)) + guard let navigation = tab.loadRequest(URLRequest(url: url)) else { + return + } + + recordNavigationInTab(tab, navigation: navigation, visitType: visitType) } } @@ -1846,7 +1850,14 @@ class BrowserViewController: UIViewController { // Only add history of a url which is not a localhost url if !tab.isPrivate { - Historyv2.add(url: url, title: tab.title ?? "", dateAdded: Date()) + // The visitType is checked If it is "typed" or not to determine the History object we are adding + // should be synced or not. This limitation exists on browser side so we are aligning with this + if let visitType = typedNavigation.first(where: { $0.key == url })?.value, + visitType == .typed { + Historyv2.add(url: url, title: tab.title ?? "", dateAdded: Date()) + } else { + Historyv2.addLocal(url: url, title: tab.title ?? "", dateAdded: Date()) + } } } diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift index e22bbb3f098..db7bf8c2c19 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift @@ -189,10 +189,14 @@ extension BrowserViewController { } func ignoreNavigationInTab(_ tab: Tab, navigation: WKNavigation) { - self.ignoredNavigation.insert(navigation) + ignoredNavigation.insert(navigation) } func recordNavigationInTab(_ tab: Tab, navigation: WKNavigation, visitType: VisitType) { - self.typedNavigation[navigation] = visitType + guard let navigationURL = tab.url else { + return + } + + typedNavigation[navigationURL] = visitType } } diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift index b517d6cdde0..e8146a940cc 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift @@ -159,13 +159,16 @@ extension BrowserViewController: TopToolbarDelegate { } func topToolbar(_ topToolbar: TopToolbarView, didSubmitText text: String) { - processAddressBar(text: text, visitType: nil) + // TopToolBar Submit Text is Typed URL Visit Type + // This visit type will be used while adding History + // And it will determine either to sync the data or not + processAddressBar(text: text, visitType: .typed) } - func processAddressBar(text: String, visitType: VisitType?) { + func processAddressBar(text: String, visitType: VisitType) { if let fixupURL = URIFixup.getURL(text) { // The user entered a URL, so use it. - finishEditingAndSubmit(fixupURL, visitType: visitType ?? .typed) + finishEditingAndSubmit(fixupURL, visitType: visitType) return } diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index c4e561e4537..b023db767c3 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -128,6 +128,11 @@ extension Historyv2 { Historyv2.historyAPI.addHistory(HistoryNode(url: url, title: title, dateAdded: dateAdded)) } + public class func addLocal(url: URL, title: String, dateAdded: Date) { + let historyNode = HistoryNode(url: url, title: title, dateAdded: dateAdded) + Historyv2.historyAPI.addHistory(historyNode, pageTransition: .LINK) + } + public static func frc() -> HistoryV2FetchResultsController? { return Historyv2Fetcher(historyAPI: Historyv2.historyAPI) } From 3ec5240dff9e096653cc23f345c8f0944c992e06 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Wed, 2 Jun 2021 15:44:07 -0400 Subject: [PATCH 18/43] Making changes on typed navigation logic --- .../Frontend/Browser/BrowserViewController.swift | 9 ++++----- .../BrowserViewController+ReaderMode.swift | 8 ++------ Shared/Extensions/URLExtensions.swift | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index f678f1ac3e6..a8777ed33b8 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -1247,11 +1247,9 @@ class BrowserViewController: UIViewController { return } - guard let navigation = tab.loadRequest(URLRequest(url: url)) else { - return - } + tab.loadRequest(URLRequest(url: url)) - recordNavigationInTab(tab, navigation: navigation, visitType: visitType) + recordNavigationInTab(url, visitType: visitType) } } @@ -1852,7 +1850,8 @@ class BrowserViewController: UIViewController { if !tab.isPrivate { // The visitType is checked If it is "typed" or not to determine the History object we are adding // should be synced or not. This limitation exists on browser side so we are aligning with this - if let visitType = typedNavigation.first(where: { $0.key == url })?.value, + if let visitType = + typedNavigation.first(where: { $0.key.typedDisplayString == url.typedDisplayString })?.value, visitType == .typed { Historyv2.add(url: url, title: tab.title ?? "", dateAdded: Date()) } else { diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift index db7bf8c2c19..f939975c2e9 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift @@ -192,11 +192,7 @@ extension BrowserViewController { ignoredNavigation.insert(navigation) } - func recordNavigationInTab(_ tab: Tab, navigation: WKNavigation, visitType: VisitType) { - guard let navigationURL = tab.url else { - return - } - - typedNavigation[navigationURL] = visitType + func recordNavigationInTab(_ url: URL, visitType: VisitType) { + typedNavigation[url] = visitType } } diff --git a/Shared/Extensions/URLExtensions.swift b/Shared/Extensions/URLExtensions.swift index 71dd09e0d33..ec02373ea3a 100644 --- a/Shared/Extensions/URLExtensions.swift +++ b/Shared/Extensions/URLExtensions.swift @@ -192,6 +192,22 @@ extension URL { return urlString } } + + public var typedDisplayString: String { + var urlString = self.absoluteString + + if urlString.hasPrefix("http://") { + urlString = String(urlString[urlString.index(urlString.startIndex, offsetBy: 7)...]) + } else if urlString.hasPrefix("https://") { + urlString = String(urlString[urlString.index(urlString.startIndex, offsetBy: 8)...]) + } + + if urlString.hasSuffix("/") { + urlString.removeLast() + } + + return urlString + } /// String suitable for displaying outside of the app, for example in notifications, were Data Detectors will /// linkify the text and make it into a openable-in-Safari link. From 4bff85e05e8530cbe091d2ecd271030ab67b14bd Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 4 Jun 2021 12:21:23 -0400 Subject: [PATCH 19/43] Fixing bookmark frequency query and history frequency query --- Client/Application/ClientPreferences.swift | 4 ++-- Client/Frontend/Browser/FrecencyQuery.swift | 23 +++++++++++-------- .../Sync/BraveCore/Bookmarks/Bookmarkv2.swift | 11 +++++---- .../Sync/BraveCore/History/Historyv2.swift | 2 +- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/Client/Application/ClientPreferences.swift b/Client/Application/ClientPreferences.swift index e0bb01304e3..9cd6dc1f30e 100644 --- a/Client/Application/ClientPreferences.swift +++ b/Client/Application/ClientPreferences.swift @@ -226,8 +226,8 @@ extension Preferences { static let syncV2BookmarksMigrationCompleted = Option(key: "chromium.migration.bookmarks", default: false) /// The boolean determine History Migration is finished on client side static let syncV2HistoryMigrationCompleted = Option(key: "chromium.migration.history", default: false) - /// The count of how many time smigration is performed on client side - the value increases with every fail attempt and after 3 tries migration marked as successful - static let syncV2ObjectMigrationCount = Option(key: "chromium.migration.bookmarks.count", default: 0) + /// The count of how many times migration is performed on client side - the value increases with every fail attempt and after 3 tries migration marked as successful + static let syncV2ObjectMigrationCount = Option(key: "chromium.migration.attempt.count", default: 0) /// Whether the device is in sync chain static let syncEnabled = Option(key: "chromium.sync.enabled", default: false) /// The sync type bookmarks enabled for the device in sync chain diff --git a/Client/Frontend/Browser/FrecencyQuery.swift b/Client/Frontend/Browser/FrecencyQuery.swift index 43d4436aadf..94f919ec82e 100644 --- a/Client/Frontend/Browser/FrecencyQuery.swift +++ b/Client/Frontend/Browser/FrecencyQuery.swift @@ -17,19 +17,24 @@ class FrecencyQuery { cancellable?.cancel() cancellable = nil - // CoreData is fast, can be fetched on main thread. This also prevents threading problems. - let historySites = History.byFrecency(query: query) - .map { Site(url: $0.url ?? "", title: $0.title ?? "") } cancellable = DispatchWorkItem { // brave-core fetch can be slow over 200ms per call, // a cancellable serial queue is used for it. - let bookmarkSites = Bookmarkv2.byFrequency(query: query) - .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } - let result = Set(historySites + bookmarkSites) - - DispatchQueue.main.async { - completion(result) + Historyv2.byFrequency(query: query) { historyList in + let historySites = historyList + .map { Site(url: $0.url ?? "", title: $0.title ?? "") } + + Bookmarkv2.byFrequency(query: query) { bookmarkList in + let bookmarkSites = bookmarkList + .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } + + let result = Set(historySites + bookmarkSites) + + DispatchQueue.main.async { + completion(result) + } + } } } diff --git a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift index de2cc245d7e..228e4b72078 100644 --- a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift +++ b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift @@ -225,14 +225,15 @@ extension Bookmarkv2 { let result = folder.bookmarkNode.children.map({ Bookmarkv2($0) }) return includeFolders ? result : result.filter({ $0.isFolder == false }) } - - public static func byFrequency(query: String? = nil) -> [WebsitePresentable] { + public static func byFrequency(query: String? = nil, _ completion: @escaping ([WebsitePresentable]) -> Void) { // Invalid query.. BraveCore doesn't store bookmarks based on last visited. // Any last visited bookmarks would show up in `History` anyway. // BraveCore automatically sorts them by date as well. - guard let query = query, !query.isEmpty else { return [] } - return Bookmarkv2.bookmarksAPI.search(withQuery: query, maxCount: 200) - .compactMap({ return !$0.isFolder ? Bookmarkv2($0) : nil }) + guard let query = query, !query.isEmpty else { return } + + Bookmarkv2.bookmarksAPI.search(withQuery: query, maxCount: 200, completion: { bookmarkResults in + completion(bookmarkResults.compactMap({ return !$0.isFolder ? Bookmarkv2($0) : nil })) + }) } public func update(customTitle: String?, url: URL?) { diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index b023db767c3..33f0ac4cfae 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -156,7 +156,7 @@ extension Historyv2 { public static func byFrequency(query: String? = nil, _ completion: @escaping ([WebsitePresentable]) -> Void) { guard let query = query, !query.isEmpty else { return } - Historyv2.historyAPI.search(withQuery: nil, maxCount: 200, completion: { historyResults in + Historyv2.historyAPI.search(withQuery: query, maxCount: 200, completion: { historyResults in completion(historyResults.map { Historyv2(with: $0) }) }) } From e9d778ec3e1590607e63a48611826d23e961daef Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 4 Jun 2021 12:25:26 -0400 Subject: [PATCH 20/43] Renaming Frequency typo on query --- Client.xcodeproj/project.pbxproj | 8 ++-- Client/Frontend/Browser/FrequencyQuery.swift | 45 +++++++++++++++++++ .../Browser/Search/SearchLoader.swift | 2 +- 3 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 Client/Frontend/Browser/FrequencyQuery.swift diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index 9526ad2d1a4..3e5ca2f45c7 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -52,7 +52,7 @@ 0A3C789F23056C910022F6D8 /* OnboardingSearchEnginesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3C789E23056C910022F6D8 /* OnboardingSearchEnginesView.swift */; }; 0A3C78A1230597DA0022F6D8 /* OnboardingShieldsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3C78A0230597DA0022F6D8 /* OnboardingShieldsViewController.swift */; }; 0A3C78A3230597F10022F6D8 /* OnboardingShieldsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A3C78A2230597F10022F6D8 /* OnboardingShieldsView.swift */; }; - 0A40450C25A47BD6009EC321 /* FrecencyQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A40450B25A47BD6009EC321 /* FrecencyQuery.swift */; }; + 0A40450C25A47BD6009EC321 /* FrequencyQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A40450B25A47BD6009EC321 /* FrequencyQuery.swift */; }; 0A4214E921A6EBCF006B8E39 /* SafeBrowsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A4214E821A6EBCF006B8E39 /* SafeBrowsingTests.swift */; }; 0A4214FF21AC0D6C006B8E39 /* TimeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A4214F621AC0AFF006B8E39 /* TimeExtensions.swift */; }; 0A42150121AC0E8E006B8E39 /* TimeExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A42150021AC0E8E006B8E39 /* TimeExtensionTests.swift */; }; @@ -1450,7 +1450,7 @@ 0A3C789E23056C910022F6D8 /* OnboardingSearchEnginesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingSearchEnginesView.swift; sourceTree = ""; }; 0A3C78A0230597DA0022F6D8 /* OnboardingShieldsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingShieldsViewController.swift; sourceTree = ""; }; 0A3C78A2230597F10022F6D8 /* OnboardingShieldsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingShieldsView.swift; sourceTree = ""; }; - 0A40450B25A47BD6009EC321 /* FrecencyQuery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrecencyQuery.swift; sourceTree = ""; }; + 0A40450B25A47BD6009EC321 /* FrequencyQuery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrequencyQuery.swift; sourceTree = ""; }; 0A4214E821A6EBCF006B8E39 /* SafeBrowsingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeBrowsingTests.swift; sourceTree = ""; }; 0A4214F621AC0AFF006B8E39 /* TimeExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeExtensions.swift; sourceTree = ""; }; 0A42150021AC0E8E006B8E39 /* TimeExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeExtensionTests.swift; sourceTree = ""; }; @@ -5119,7 +5119,7 @@ D3B6923E1B9F9A58004B87A4 /* FindInPageHelper.swift */, 39F4C1092045DB2E00746155 /* FocusHelper.swift */, D0E55C4E1FB4FD23006DC274 /* FormPostHelper.swift */, - 0A40450B25A47BD6009EC321 /* FrecencyQuery.swift */, + 0A40450B25A47BD6009EC321 /* FrequencyQuery.swift */, 39DD030C1CD53E1900BC09B3 /* HomePageHelper.swift */, D3C3696D1CC6B78800348A61 /* LocalRequestHelper.swift */, 0BB5B30A1AC0AD1F0052877D /* LoginsHelper.swift */, @@ -7059,7 +7059,7 @@ 27733E5826977EC40086799A /* PasscodeMigrationView.swift in Sources */, 2726637324981B600056CFE1 /* FeedSectionHeaderView.swift in Sources */, 27C461DE211B76500088A441 /* ShieldsView.swift in Sources */, - 0A40450C25A47BD6009EC321 /* FrecencyQuery.swift in Sources */, + 0A40450C25A47BD6009EC321 /* FrequencyQuery.swift in Sources */, E4B423DD1ABA0318007E66C8 /* ReaderModeHandlers.swift in Sources */, 276A791024476FD200AC9446 /* StatsSectionProvider.swift in Sources */, 27FCA8E02447708300A8CA48 /* FavoritesSectionProvider.swift in Sources */, diff --git a/Client/Frontend/Browser/FrequencyQuery.swift b/Client/Frontend/Browser/FrequencyQuery.swift new file mode 100644 index 00000000000..f5f0929a9ae --- /dev/null +++ b/Client/Frontend/Browser/FrequencyQuery.swift @@ -0,0 +1,45 @@ +// Copyright 2020 The Brave Authors. All rights reserved. +// 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 Shared +import Storage +import Data + +class FrequencyQuery { + private static let queue = DispatchQueue(label: "frequency-query-queue") + private static var cancellable: DispatchWorkItem? + + public static func sitesByFrecency(containing query: String? = nil, + completion: @escaping (Set) -> Void) { + cancellable?.cancel() + cancellable = nil + + cancellable = DispatchWorkItem { + // brave-core fetch can be slow over 200ms per call, + // a cancellable serial queue is used for it. + + Historyv2.byFrequency(query: query) { historyList in + let historySites = historyList + .map { Site(url: $0.url ?? "", title: $0.title ?? "") } + + Bookmarkv2.byFrequency(query: query) { bookmarkList in + let bookmarkSites = bookmarkList + .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } + + let result = Set(historySites + bookmarkSites) + + DispatchQueue.main.async { + completion(result) + } + } + } + } + + if let task = cancellable { + queue.async(execute: task) + } + } +} diff --git a/Client/Frontend/Browser/Search/SearchLoader.swift b/Client/Frontend/Browser/Search/SearchLoader.swift index f37e95f0122..050163a47bd 100644 --- a/Client/Frontend/Browser/Search/SearchLoader.swift +++ b/Client/Frontend/Browser/Search/SearchLoader.swift @@ -18,7 +18,7 @@ class SearchLoader: Loader<[Site], SearchViewController> { return } - FrecencyQuery.sitesByFrecency(containing: query) { [weak self] result in + FrequencyQuery.sitesByFrecency(containing: query) { [weak self] result in guard let self = self else { return } self.load(Array(result)) From bdfbf7543d47bed64c5a7e72352dc225bea65934 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 4 Jun 2021 12:26:37 -0400 Subject: [PATCH 21/43] Deleting removed files --- Client/Frontend/Browser/FrecencyQuery.swift | 45 --------------------- 1 file changed, 45 deletions(-) delete mode 100644 Client/Frontend/Browser/FrecencyQuery.swift diff --git a/Client/Frontend/Browser/FrecencyQuery.swift b/Client/Frontend/Browser/FrecencyQuery.swift deleted file mode 100644 index 94f919ec82e..00000000000 --- a/Client/Frontend/Browser/FrecencyQuery.swift +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 The Brave Authors. All rights reserved. -// 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 Shared -import Storage -import Data - -class FrecencyQuery { - private static let queue = DispatchQueue(label: "frecency-query-queue") - private static var cancellable: DispatchWorkItem? - - public static func sitesByFrecency(containing query: String? = nil, - completion: @escaping (Set) -> Void) { - cancellable?.cancel() - cancellable = nil - - cancellable = DispatchWorkItem { - // brave-core fetch can be slow over 200ms per call, - // a cancellable serial queue is used for it. - - Historyv2.byFrequency(query: query) { historyList in - let historySites = historyList - .map { Site(url: $0.url ?? "", title: $0.title ?? "") } - - Bookmarkv2.byFrequency(query: query) { bookmarkList in - let bookmarkSites = bookmarkList - .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } - - let result = Set(historySites + bookmarkSites) - - DispatchQueue.main.async { - completion(result) - } - } - } - } - - if let task = cancellable { - queue.async(execute: task) - } - } -} From c7d0e748db140bf934adf074e1b78348a26d6a92 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 4 Jun 2021 12:47:20 -0400 Subject: [PATCH 22/43] Fixing merge conflict Strings Brave --- BraveShared/BraveStrings.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BraveShared/BraveStrings.swift b/BraveShared/BraveStrings.swift index 7aba9e5bf8b..810750def22 100644 --- a/BraveShared/BraveStrings.swift +++ b/BraveShared/BraveStrings.swift @@ -2228,8 +2228,8 @@ extension Strings { } extension Strings { - public struct BraveToday { - public static let braveToday = NSLocalizedString( + public struct BraveNews { + public static let braveNews = NSLocalizedString( "today.braveToday", bundle: .braveShared, value: "Brave News", From 83359b5fe66a6ce0268718131fec25d4d670de6a Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 4 Jun 2021 15:56:42 -0400 Subject: [PATCH 23/43] Concurrency is removed for core fetched objects --- Client/Frontend/Browser/FrequencyQuery.swift | 39 ++++++------------- .../Browser/Search/SearchLoader.swift | 2 +- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/Client/Frontend/Browser/FrequencyQuery.swift b/Client/Frontend/Browser/FrequencyQuery.swift index f5f0929a9ae..5a6ec52014b 100644 --- a/Client/Frontend/Browser/FrequencyQuery.swift +++ b/Client/Frontend/Browser/FrequencyQuery.swift @@ -9,37 +9,22 @@ import Storage import Data class FrequencyQuery { - private static let queue = DispatchQueue(label: "frequency-query-queue") - private static var cancellable: DispatchWorkItem? - public static func sitesByFrecency(containing query: String? = nil, - completion: @escaping (Set) -> Void) { - cancellable?.cancel() - cancellable = nil + public static func sitesByFrequency(containing query: String? = nil, + completion: @escaping (Set) -> Void) { - cancellable = DispatchWorkItem { - // brave-core fetch can be slow over 200ms per call, - // a cancellable serial queue is used for it. + Historyv2.byFrequency(query: query) { historyList in + let historySites = historyList + .map { Site(url: $0.url ?? "", title: $0.title ?? "") } - Historyv2.byFrequency(query: query) { historyList in - let historySites = historyList - .map { Site(url: $0.url ?? "", title: $0.title ?? "") } - - Bookmarkv2.byFrequency(query: query) { bookmarkList in - let bookmarkSites = bookmarkList - .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } - - let result = Set(historySites + bookmarkSites) - - DispatchQueue.main.async { - completion(result) - } - } + Bookmarkv2.byFrequency(query: query) { bookmarkList in + let bookmarkSites = bookmarkList + .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } + + let result = Set(historySites + bookmarkSites) + + completion(result) } } - - if let task = cancellable { - queue.async(execute: task) - } } } diff --git a/Client/Frontend/Browser/Search/SearchLoader.swift b/Client/Frontend/Browser/Search/SearchLoader.swift index 050163a47bd..fa74b4c8c28 100644 --- a/Client/Frontend/Browser/Search/SearchLoader.swift +++ b/Client/Frontend/Browser/Search/SearchLoader.swift @@ -18,7 +18,7 @@ class SearchLoader: Loader<[Site], SearchViewController> { return } - FrequencyQuery.sitesByFrecency(containing: query) { [weak self] result in + FrequencyQuery.sitesByFrequency(containing: query) { [weak self] result in guard let self = self else { return } self.load(Array(result)) From 392ca92c92894e9149604a68530b56883035ba92 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 4 Jun 2021 16:55:27 -0400 Subject: [PATCH 24/43] Instance share for API --- Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift | 2 +- Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift | 4 ++-- Client/Frontend/Sync/BraveCore/History/Historyv2.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift index 228e4b72078..4523de69a5b 100644 --- a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift +++ b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift @@ -17,7 +17,7 @@ private let log = Logger.browserLogger class Bookmarkv2: WebsitePresentable { private let bookmarkNode: BookmarkNode private var observer: BookmarkModelListener? - private static let bookmarksAPI = BraveBookmarksAPI() + private static let bookmarksAPI = BraveBookmarksAPI.shared init(_ bookmarkNode: BookmarkNode) { self.bookmarkNode = bookmarkNode diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 8d208fe6612..03acf0cbd91 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -37,8 +37,8 @@ class BraveCoreMigrator { private var bookmarkMigrationState: MigrationState = .notStarted private var historyMigrationState: MigrationState = .notStarted - private let bookmarksAPI = BraveBookmarksAPI() - private let historyAPI = BraveHistoryAPI() + private let bookmarksAPI = BraveBookmarksAPI.shared + private let historyAPI = BraveHistoryAPI.shared private let dataImportExporter = BraveCoreImportExportUtility() private var bookmarkObserver: BookmarkModelListener? private var historyObserver: HistoryServiceListener? diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index 33f0ac4cfae..79f5fa6c274 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -85,7 +85,7 @@ class Historyv2: WebsitePresentable { // MARK: Private private let historyNode: HistoryNode - private static let historyAPI = BraveHistoryAPI() + private static let historyAPI = BraveHistoryAPI.shared private func fetchHistoryTimePeriod(visited: Date?) -> Section? { let todayOffset = 0 From df615f5b132cc0874533efb44b1ff4aa22798efb Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 14 Jun 2021 15:54:17 -0400 Subject: [PATCH 25/43] Fixing Changes in VisitType after rebase --- Client.xcodeproj/project.pbxproj | 2 -- Client/Application/Migration.swift | 1 - .../Browser/BrowserViewController.swift | 2 +- .../BrowserViewController+ReaderMode.swift | 22 +++++++++++++ ...rowserViewController+ToolbarDelegate.swift | 2 +- Client/Frontend/Browser/VisitType.swift | 32 ------------------- 6 files changed, 24 insertions(+), 37 deletions(-) delete mode 100644 Client/Frontend/Browser/VisitType.swift diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index 3e5ca2f45c7..400e68705d8 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -5161,7 +5161,6 @@ 4452CAEF255412800053EFE6 /* DefaultBrowserIntroCalloutViewController.swift */, 0A0A5ED025B1F080007B3E74 /* DefaultBrowserIntroManager.swift */, 0AE50869261C6F2E0099C6A3 /* BraveSearchHelper.swift */, - 2F5893D5265FEF7E002323D9 /* VisitType.swift */, ); indentWidth = 4; path = Browser; @@ -7134,7 +7133,6 @@ 27FD2CAD2146C31C00A5A779 /* AddToFavoritesActivity.swift in Sources */, 4422D4E121BFFB7600BF1855 /* filter_block.cc in Sources */, 0A8C69BE225E350300988715 /* IndentedImageTableViewCell.swift in Sources */, - 2F5893D6265FEF7E002323D9 /* VisitType.swift in Sources */, 0AE5C69124F0059D004CBC9B /* OnboardingPrivacyConsentViewController.swift in Sources */, 5E096180252B63F200F3AFBB /* BraveSyncAPI+Utilities.swift in Sources */, 5E5E6E3A25BA03510035B6A0 /* PlaylistViewController.swift in Sources */, diff --git a/Client/Application/Migration.swift b/Client/Application/Migration.swift index 52f8a7f31c5..7f352e090b4 100644 --- a/Client/Application/Migration.swift +++ b/Client/Application/Migration.swift @@ -14,7 +14,6 @@ private let log = Logger.browserLogger class Migration { private(set) public static var braveCoreSyncObjectsMigrator: BraveCoreMigrator? - private(set) public static var profileSyncService: BraveSyncProfileService? private(set) public static var isChromiumMigrationCompleted: Bool = { return Preferences.Chromium.syncV2BookmarksMigrationCompleted.value && diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index a8777ed33b8..7e67bef0733 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -2081,7 +2081,7 @@ extension BrowserViewController: TabDelegate { extension BrowserViewController: SearchViewControllerDelegate { func searchViewController(_ searchViewController: SearchViewController, didSubmit query: String) { topToolbar.leaveOverlayMode() - processAddressBar(text: query) + processAddressBar(text: query, visitType: .typed) } func searchViewController(_ searchViewController: SearchViewController, didSelectURL url: URL) { diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift index f939975c2e9..acc8de884a5 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift @@ -7,6 +7,28 @@ import Shared import WebKit import Storage +// MARK: VisitType + +enum VisitType: Int { + case unknown + /** + * This transition type means the user followed a link and got a new toplevel + * window. + */ + case link + + /** + * This transition type means that the user typed the page's URL in the + * URL bar or selected it from URL bar autocomplete results. + */ + case typed + /** + * This transition type means that user opened a link from bookmarks. + */ + case bookmark + case download +} + // MARK: - ReaderModeDelegate extension BrowserViewController: ReaderModeDelegate { diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift index e8146a940cc..f5f7a116c32 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ToolbarDelegate.swift @@ -354,7 +354,7 @@ extension BrowserViewController: TopToolbarDelegate { let submitSearch = { [weak self] (text: String) in if let fixupURL = URIFixup.getURL(text) { - self?.finishEditingAndSubmit(fixupURL, isBookmark: false) + self?.finishEditingAndSubmit(fixupURL, visitType: .unknown) return } diff --git a/Client/Frontend/Browser/VisitType.swift b/Client/Frontend/Browser/VisitType.swift deleted file mode 100644 index 5b02a29f3e1..00000000000 --- a/Client/Frontend/Browser/VisitType.swift +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2021 The Brave Authors. All rights reserved. -// 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 - -// These are taken from the Places docs -// http://mxr.mozilla.org/mozilla-central/source/toolkit/components/places/nsINavHistoryService.idl#1187 -enum VisitType: Int { - case unknown = 0 - - /** - * This transition type means the user followed a link and got a new toplevel - * window. - */ - case link = 1 - - /** - * This transition type means that the user typed the page's URL in the - * URL bar or selected it from URL bar autocomplete results, clicked on - * it from a history query (from the History sidebar, History menu, - * or history query in the personal toolbar or Places organizer). - */ - case typed = 2 - - case bookmark = 3 - case embed = 4 - case permanentRedirect = 5 - case temporaryRedirect = 6 - case download = 7 - case framedLink = 8 -} From 8ca1158bf3862cbf69cdfde480203ce7a647cb88 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 18 Jun 2021 16:09:14 -0400 Subject: [PATCH 26/43] Making changes for integrate Brace Core API changes --- .../Browser/BrowserViewController.swift | 2 +- .../NewTabPageViewController.swift | 28 ++--- .../AddEditBookmarkTableViewController.swift | 8 +- .../Sync/BraveCore/Bookmarks/Bookmarkv2.swift | 102 +++++++++++++----- .../Sync/BraveCore/BraveCoreMigrator.swift | 22 ++-- .../BraveCore/BraveSyncAPI+Utilities.swift | 11 +- .../Sync/BraveCore/History/Historyv2.swift | 54 +++++++--- 7 files changed, 157 insertions(+), 70 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index 7e67bef0733..05949cccc8f 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -1855,7 +1855,7 @@ class BrowserViewController: UIViewController { visitType == .typed { Historyv2.add(url: url, title: tab.title ?? "", dateAdded: Date()) } else { - Historyv2.addLocal(url: url, title: tab.title ?? "", dateAdded: Date()) + Historyv2.add(url: url, title: tab.title ?? "", dateAdded: Date(), isURLTyped: false) } } } diff --git a/Client/Frontend/Browser/New Tab Page/NewTabPageViewController.swift b/Client/Frontend/Browser/New Tab Page/NewTabPageViewController.swift index a1427c7ed49..3cfb4b38906 100644 --- a/Client/Frontend/Browser/New Tab Page/NewTabPageViewController.swift +++ b/Client/Frontend/Browser/New Tab Page/NewTabPageViewController.swift @@ -232,7 +232,7 @@ class NewTabPageViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - reportSponsoredImageBackgroundEvent(.viewed) +// reportSponsoredImageBackgroundEvent(.viewed) presentNotification() } @@ -377,18 +377,18 @@ class NewTabPageViewController: UIViewController { backgroundView.imageConstraints?.landscapeCenter.update(offset: inset) } - private func reportSponsoredImageBackgroundEvent(_ event: NewTabPageAdEventType) { - guard let backgroundType = background.currentBackground?.type, - case .withBrandLogo = backgroundType, - let creativeInstanceId = background.currentBackground?.wallpaper.creativeInstanceId else { - return - } - rewards.ads.reportNewTabPageAdEvent( - background.wallpaperId.uuidString, - creativeInstanceId: creativeInstanceId, - eventType: event - ) - } +// private func reportSponsoredImageBackgroundEvent(_ event: NewTabPageAdEventType) { +// guard let backgroundType = background.currentBackground?.type, +// case .withBrandLogo = backgroundType, +// let creativeInstanceId = background.currentBackground?.wallpaper.creativeInstanceId else { +// return +// } +// rewards.ads.reportNewTabPageAdEvent( +// background.wallpaperId.uuidString, +// creativeInstanceId: creativeInstanceId, +// eventType: event +// ) +// } // MARK: - Notifications @@ -673,7 +673,7 @@ class NewTabPageViewController: UIViewController { UIImpactFeedbackGenerator(style: .medium).bzzt() delegate?.navigateToInput(logo.destinationUrl, inNewTab: false, switchingToPrivateMode: false) - reportSponsoredImageBackgroundEvent(.clicked) +// reportSponsoredImageBackgroundEvent(.clicked) } private func tappedQRCode(_ code: String) { diff --git a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/AddEditBookmarkTableViewController.swift b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/AddEditBookmarkTableViewController.swift index 74c38e230b4..7dc6b856790 100644 --- a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/AddEditBookmarkTableViewController.swift +++ b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/Bookmarks/AddEditBookmarkTableViewController.swift @@ -113,7 +113,7 @@ class AddEditBookmarkTableViewController: UITableViewController { // MARK: - Init - private var frc: BookmarksV2FetchResultsController + private var frc: BookmarksV2FetchResultsController? private let mode: BookmarkEditMode private var presentationMode: DataSourcePresentationMode @@ -148,7 +148,7 @@ class AddEditBookmarkTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() - frc.delegate = self + frc?.delegate = self title = mode.title navigationItem.rightBarButtonItem = saveButton @@ -196,7 +196,7 @@ class AddEditBookmarkTableViewController: UITableViewController { /// Indentation level starts with 0, but level 0 is designed for special folders /// (root level bookamrks, favorites). private func sortFolders() -> [IndentedFolder] { - guard let objects = frc.fetchedObjects else { return [] } + guard let objects = frc?.fetchedObjects else { return [] } return objects.map({ if let folder = $0 as? BraveBookmarkFolder { return IndentedFolder(folder, folder.indentationLevel) @@ -206,7 +206,7 @@ class AddEditBookmarkTableViewController: UITableViewController { } private func reloadData() { - try? frc.performFetch() + try? frc?.performFetch() sortedFolders = sortFolders() // If the folder we want to save to was deleted, UI needs an update diff --git a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift index 4523de69a5b..30fc66231f0 100644 --- a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift +++ b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift @@ -16,8 +16,8 @@ private let log = Logger.browserLogger // with the same layout/interface as `Bookmark (from CoreData)` class Bookmarkv2: WebsitePresentable { private let bookmarkNode: BookmarkNode - private var observer: BookmarkModelListener? - private static let bookmarksAPI = BraveBookmarksAPI.shared + private var bookmarkFavIconObserver: BookmarkModelListener? + private static var bookmarkModelLoadedObserver: BookmarkModelListener? init(_ bookmarkNode: BookmarkNode) { self.bookmarkNode = bookmarkNode @@ -61,12 +61,16 @@ class Bookmarkv2: WebsitePresentable { } public var parent: Bookmarkv2? { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return nil + } + if let parent = bookmarkNode.parent { // Return nil if the parent is the ROOT node // because AddEditBookmarkTableViewController.sortFolders // sorts root folders by having a nil parent. // If that code changes, we should change here to match. - if bookmarkNode.parent?.guid != Bookmarkv2.bookmarksAPI.rootNode?.guid { + if bookmarkNode.parent?.guid != bookmarksAPI.rootNode?.guid { return Bookmarkv2(parent) } } @@ -100,8 +104,12 @@ class Bookmarkv2: WebsitePresentable { } public func delete() { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return + } + if self.canBeDeleted { - Bookmarkv2.bookmarksAPI.removeBookmark(bookmarkNode) + bookmarksAPI.removeBookmark(bookmarkNode) } } @@ -109,6 +117,10 @@ class Bookmarkv2: WebsitePresentable { // If no folder was visited, returns the mobile bookmarks folder // If the root folder was visited, returns nil public static func lastVisitedFolder() -> Bookmarkv2? { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return nil + } + guard Preferences.General.showLastVisitedBookmarksFolder.value, let nodeId = Preferences.Chromium.lastBookmarksFolderNodeId.value else { // Default folder is the mobile node.. @@ -124,7 +136,7 @@ class Bookmarkv2: WebsitePresentable { } // Display last visited folder.. - if let folderNode = Bookmarkv2.bookmarksAPI.getNodeById(nodeId), + if let folderNode = bookmarksAPI.getNodeById(nodeId), folderNode.isVisible { return Bookmarkv2(folderNode) } @@ -137,9 +149,13 @@ class Bookmarkv2: WebsitePresentable { } public static func lastFolderPath() -> [Bookmarkv2] { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return [] + } + if Preferences.General.showLastVisitedBookmarksFolder.value, let nodeId = Preferences.Chromium.lastBookmarksFolderNodeId.value, - var folderNode = Bookmarkv2.bookmarksAPI.getNodeById(nodeId), + var folderNode = bookmarksAPI.getNodeById(nodeId), folderNode.isVisible { // We don't ever display the root node @@ -187,25 +203,37 @@ class BraveBookmarkFolder: Bookmarkv2 { extension Bookmarkv2 { public class func mobileNode() -> Bookmarkv2? { - if let node = Bookmarkv2.bookmarksAPI.mobileNode { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return nil + } + + if let node = bookmarksAPI.mobileNode { return Bookmarkv2(node) } return nil } public class func addFolder(title: String, parentFolder: Bookmarkv2? = nil) { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return + } + if let parentFolder = parentFolder?.bookmarkNode { - Bookmarkv2.bookmarksAPI.createFolder(withParent: parentFolder, title: title) + bookmarksAPI.createFolder(withParent: parentFolder, title: title) } else { - Bookmarkv2.bookmarksAPI.createFolder(withTitle: title) + bookmarksAPI.createFolder(withTitle: title) } } public class func add(url: URL, title: String?, parentFolder: Bookmarkv2? = nil) { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return + } + if let parentFolder = parentFolder?.bookmarkNode { - Bookmarkv2.bookmarksAPI.createBookmark(withParent: parentFolder, title: title ?? "", with: url) + bookmarksAPI.createBookmark(withParent: parentFolder, title: title ?? "", with: url) } else { - Bookmarkv2.bookmarksAPI.createBookmark(withTitle: title ?? "", url: url) + bookmarksAPI.createBookmark(withTitle: title ?? "", url: url) } } @@ -214,11 +242,19 @@ extension Bookmarkv2 { } public static func frc(parent: Bookmarkv2?) -> BookmarksV2FetchResultsController? { - return Bookmarkv2Fetcher(parent?.bookmarkNode, api: Bookmarkv2.bookmarksAPI) + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return nil + } + + return Bookmarkv2Fetcher(parent?.bookmarkNode, api: bookmarksAPI) } - public static func foldersFrc(excludedFolder: Bookmarkv2? = nil) -> BookmarksV2FetchResultsController { - return Bookmarkv2ExclusiveFetcher(excludedFolder?.bookmarkNode, api: Bookmarkv2.bookmarksAPI) + public static func foldersFrc(excludedFolder: Bookmarkv2? = nil) -> BookmarksV2FetchResultsController? { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return nil + } + + return Bookmarkv2ExclusiveFetcher(excludedFolder?.bookmarkNode, api: bookmarksAPI) } public static func getChildren(forFolder folder: Bookmarkv2, includeFolders: Bool) -> [Bookmarkv2]? { @@ -229,9 +265,12 @@ extension Bookmarkv2 { // Invalid query.. BraveCore doesn't store bookmarks based on last visited. // Any last visited bookmarks would show up in `History` anyway. // BraveCore automatically sorts them by date as well. - guard let query = query, !query.isEmpty else { return } + guard let query = query, !query.isEmpty, + let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return + } - Bookmarkv2.bookmarksAPI.search(withQuery: query, maxCount: 200, completion: { bookmarkResults in + bookmarksAPI.search(withQuery: query, maxCount: 200, completion: { bookmarkResults in completion(bookmarkResults.compactMap({ return !$0.isFolder ? Bookmarkv2($0) : nil })) }) } @@ -242,7 +281,11 @@ extension Bookmarkv2 { } public func updateWithNewLocation(customTitle: String?, url: URL?, location: Bookmarkv2?) { - if let location = location?.bookmarkNode ?? Bookmarkv2.bookmarksAPI.mobileNode { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return + } + + if let location = location?.bookmarkNode ?? bookmarksAPI.mobileNode { if location.guid != bookmarkNode.parent?.guid { bookmarkNode.move(toParent: location) } @@ -263,7 +306,10 @@ extension Bookmarkv2 { public class func reorderBookmarks(frc: BookmarksV2FetchResultsController?, sourceIndexPath: IndexPath, destinationIndexPath: IndexPath) { - guard let frc = frc else { return } + guard let frc = frc, + let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return + } if let node = frc.object(at: sourceIndexPath)?.bookmarkNode, let parent = node.parent ?? bookmarksAPI.mobileNode { @@ -299,6 +345,10 @@ extension Bookmarkv2 { } public func addFavIconObserver(_ observer: @escaping () -> Void) { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return + } + let observer = BookmarkModelStateObserver { [weak self] state in guard let self = self else { return } @@ -310,24 +360,28 @@ extension Bookmarkv2 { } } - self.observer = Bookmarkv2.bookmarksAPI.add(observer) + self.bookmarkFavIconObserver = bookmarksAPI.add(observer) } public func removeFavIconObserver() { - observer = nil + bookmarkFavIconObserver = nil } public static func waitForBookmarkModelLoaded(_ completion: @escaping () -> Void) { + guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + return + } + if bookmarksAPI.isLoaded { DispatchQueue.main.async { completion() } } else { - var observer: BookmarkModelListener? - observer = Bookmarkv2.bookmarksAPI.add(BookmarkModelStateObserver({ + //var observer: BookmarkModelListener? + bookmarkModelLoadedObserver = bookmarksAPI.add(BookmarkModelStateObserver({ if case .modelLoaded = $0 { - observer?.destroy() - observer = nil + bookmarkModelLoadedObserver?.destroy() + bookmarkModelLoadedObserver = nil DispatchQueue.main.async { completion() diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 03acf0cbd91..2da55387626 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -37,8 +37,9 @@ class BraveCoreMigrator { private var bookmarkMigrationState: MigrationState = .notStarted private var historyMigrationState: MigrationState = .notStarted - private let bookmarksAPI = BraveBookmarksAPI.shared - private let historyAPI = BraveHistoryAPI.shared + private var bookmarksAPI: BraveBookmarksAPI? + private var historyAPI: BraveHistoryAPI? + private let dataImportExporter = BraveCoreImportExportUtility() private var bookmarkObserver: BookmarkModelListener? private var historyObserver: HistoryServiceListener? @@ -49,6 +50,11 @@ class BraveCoreMigrator { migrationObserver = .completed } + if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) { + bookmarksAPI = appDelegate.braveCore?.bookmarksAPI + historyAPI = appDelegate.braveCore?.historyAPI + } + #if TEST_MIGRATION var didFinishTest = false // Add fake bookmarks to CoreData @@ -139,13 +145,13 @@ extension BraveCoreMigrator { if !Preferences.Chromium.syncV2BookmarksMigrationCompleted.value { // If the bookmark model has already loaded, the observer does NOT get called! // Therefore we should continue to migrate the bookmarks - if bookmarksAPI.isLoaded { + if bookmarksAPI?.isLoaded == true { performBookmarkMigrationIfNeeded { success in completion(success) } } else { // Wait for the bookmark model to load before we attempt to perform migration! - self.bookmarkObserver = bookmarksAPI.add(BookmarksModelLoadedObserver({ [weak self] in + self.bookmarkObserver = bookmarksAPI?.add(BookmarksModelLoadedObserver({ [weak self] in guard let self = self else { return } self.bookmarkObserver?.destroy() self.bookmarkObserver = nil @@ -187,7 +193,7 @@ extension BraveCoreMigrator { private func migrateBookmarks(_ completion: @escaping (_ success: Bool) -> Void) { // Migrate to the mobile folder by default.. - guard let rootFolder = bookmarksAPI.mobileNode else { + guard let rootFolder = bookmarksAPI?.mobileNode else { log.error("Invalid Root Folder - Mobile Node") DispatchQueue.main.async { completion(false) @@ -261,13 +267,13 @@ extension BraveCoreMigrator { if !Preferences.Chromium.syncV2HistoryMigrationCompleted.value { // If the history model has already loaded, the observer does NOT get called! // Therefore we should continue to migrate the history - if historyAPI.isLoaded { + if historyAPI?.isBackendLoaded == true { performHistoryMigrationIfNeeded { success in completion(success) } } else { // Wait for the history service to load before we attempt to perform migration! - self.historyObserver = historyAPI.add(HistoryServiceLoadedObserver({ [weak self] in + self.historyObserver = historyAPI?.add(HistoryServiceLoadedObserver({ [weak self] in guard let self = self else { return } self.historyObserver?.destroy() self.historyObserver = nil @@ -316,7 +322,7 @@ extension BraveCoreMigrator { } let historyNode = HistoryNode(url: url, title: title, dateAdded: dateAdded) - historyAPI.addHistory(historyNode) + historyAPI?.addHistory(historyNode, isURLTyped: true) return true } diff --git a/Client/Frontend/Sync/BraveCore/BraveSyncAPI+Utilities.swift b/Client/Frontend/Sync/BraveCore/BraveSyncAPI+Utilities.swift index d015fcb4b75..80476c3e922 100644 --- a/Client/Frontend/Sync/BraveCore/BraveSyncAPI+Utilities.swift +++ b/Client/Frontend/Sync/BraveCore/BraveSyncAPI+Utilities.swift @@ -41,14 +41,19 @@ extension BraveSyncAPI { } func enableSyncTypes() { - BraveSyncProfileService.shared.userSelectedTypes = [] + guard let syncProfileService = + (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.syncProfileService else { + return + } + + syncProfileService.userSelectedTypes = [] if Preferences.Chromium.syncBookmarksEnabled.value { - BraveSyncProfileService.shared.userSelectedTypes.update(with: .BOOKMARKS) + syncProfileService.userSelectedTypes.update(with: .BOOKMARKS) } if Preferences.Chromium.syncHistoryEnabled.value { - BraveSyncProfileService.shared.userSelectedTypes.update(with: .HISTORY) + syncProfileService.userSelectedTypes.update(with: .HISTORY) } } diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index 79f5fa6c274..61baa7d1beb 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -85,7 +85,7 @@ class Historyv2: WebsitePresentable { // MARK: Private private let historyNode: HistoryNode - private static let historyAPI = BraveHistoryAPI.shared + private static var observer: HistoryServiceListener? private func fetchHistoryTimePeriod(visited: Date?) -> Section? { let todayOffset = 0 @@ -124,39 +124,58 @@ class Historyv2: WebsitePresentable { extension Historyv2 { - public class func add(url: URL, title: String, dateAdded: Date) { - Historyv2.historyAPI.addHistory(HistoryNode(url: url, title: title, dateAdded: dateAdded)) - } - - public class func addLocal(url: URL, title: String, dateAdded: Date) { + public class func add(url: URL, title: String, dateAdded: Date, isURLTyped: Bool = true) { + guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + return + } + let historyNode = HistoryNode(url: url, title: title, dateAdded: dateAdded) - Historyv2.historyAPI.addHistory(historyNode, pageTransition: .LINK) + historyAPI.addHistory(historyNode, isURLTyped: isURLTyped) } public static func frc() -> HistoryV2FetchResultsController? { - return Historyv2Fetcher(historyAPI: Historyv2.historyAPI) + guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + return nil + } + + return Historyv2Fetcher(historyAPI: historyAPI) } public func delete() { - Historyv2.historyAPI.removeHistory(historyNode) + guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + return + } + + historyAPI.removeHistory(historyNode) } public class func deleteAll(_ completion: @escaping () -> Void) { - Historyv2.historyAPI.removeAll { + guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + return + } + + historyAPI.removeAll { completion() } } public class func suffix(_ maxLength: Int, _ completion: @escaping ([Historyv2]) -> Void) { - Historyv2.historyAPI.search(withQuery: nil, maxCount: UInt(max(20, maxLength)), completion: { historyResults in + guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + return + } + + historyAPI.search(withQuery: nil, maxCount: UInt(max(20, maxLength)), completion: { historyResults in completion(historyResults.map { Historyv2(with: $0) }) }) } public static func byFrequency(query: String? = nil, _ completion: @escaping ([WebsitePresentable]) -> Void) { - guard let query = query, !query.isEmpty else { return } + guard let query = query, !query.isEmpty, + let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + return + } - Historyv2.historyAPI.search(withQuery: query, maxCount: 200, completion: { historyResults in + historyAPI.search(withQuery: query, maxCount: 200, completion: { historyResults in completion(historyResults.map { Historyv2(with: $0) }) }) } @@ -177,13 +196,16 @@ extension Historyv2 { extension Historyv2 { public static func waitForHistoryServiceLoaded(_ completion: @escaping () -> Void) { - if historyAPI.isLoaded { + guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + return + } + + if historyAPI.isBackendLoaded { DispatchQueue.main.async { completion() } } else { - var observer: HistoryServiceListener? - observer = Historyv2.historyAPI.add(HistoryServiceStateObserver({ + observer = historyAPI.add(HistoryServiceStateObserver({ if case .serviceLoaded = $0 { observer?.destroy() observer = nil From 7d410c45ec3e6bf57a5304757e7ae9fb316ba005 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 29 Jun 2021 13:52:22 -0400 Subject: [PATCH 27/43] Bump Brave Core library to 1.26.x --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5430c11ad14..b71500b5b10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1043,8 +1043,8 @@ } }, "brave-core-ios": { - "version": "https://github.com/brave/brave-browser/releases/download/v1.25.69/brave-core-ios-1.25.69.tgz", - "integrity": "sha512-suFJJ/uvWoTA5PSakyJjmH0M5htP6S28WgtVuGeBS89fw/GOPAW2tVl7VBDherMFcCG/ScSii1tnF6nq9bhHgA==" + "version": "https://github.com/brave/brave-browser/releases/download/v1.26.71/brave-core-ios-1.26.71.tgz", + "integrity": "sha512-pZL9JDR+aId4IeaMiT6elMmnofAqpNB4T+NAkBafOzbtnjFRNuKhy4oOtEOQz/AtsORN1bRXAFA4C0UJCs5PVg==" }, "browserslist": { "version": "3.2.8", diff --git a/package.json b/package.json index 478d0f8c764..6a67f5ba703 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "license": "MPL-2.0", "dependencies": { - "brave-core-ios": "https://github.com/brave/brave-browser/releases/download/v1.25.69/brave-core-ios-1.25.69.tgz", + "brave-core-ios": "https://github.com/brave/brave-browser/releases/download/v1.26.71/brave-core-ios-1.26.71.tgz", "page-metadata-parser": "^1.1.3", "readability": "github:mozilla/readability#b9f47bcc8d3c223cabe2dec6a42eeb3bd778d85c", "webpack-cli": "^3.3.10" From e930a4ef858a0b1c36bc62f96a37ba29b0059c75 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 29 Jun 2021 15:14:32 -0400 Subject: [PATCH 28/43] Changing Bookmark Frequency Fetch (POST-TASK is not uplifted to 1.26) --- Client/Frontend/Browser/FrequencyQuery.swift | 19 +++++++++++++++---- .../Sync/BraveCore/Bookmarks/Bookmarkv2.swift | 10 +++++----- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Client/Frontend/Browser/FrequencyQuery.swift b/Client/Frontend/Browser/FrequencyQuery.swift index 5a6ec52014b..97c04f5fbe8 100644 --- a/Client/Frontend/Browser/FrequencyQuery.swift +++ b/Client/Frontend/Browser/FrequencyQuery.swift @@ -10,6 +10,9 @@ import Data class FrequencyQuery { + private static let queue = DispatchQueue(label: "frequency-query-queue") + private static var cancellable: DispatchWorkItem? + public static func sitesByFrequency(containing query: String? = nil, completion: @escaping (Set) -> Void) { @@ -17,14 +20,22 @@ class FrequencyQuery { let historySites = historyList .map { Site(url: $0.url ?? "", title: $0.title ?? "") } - Bookmarkv2.byFrequency(query: query) { bookmarkList in - let bookmarkSites = bookmarkList + cancellable = DispatchWorkItem { + // brave-core fetch can be slow over 200ms per call, + // a cancellable serial queue is used for it. + let bookmarkSites = Bookmarkv2.byFrequency(query: query) .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } - let result = Set(historySites + bookmarkSites) + let result = Set(historySites+bookmarkSites) - completion(result) + DispatchQueue.main.async { + completion(result) + } } } + + if let task = cancellable { + queue.async(execute: task) + } } } diff --git a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift index 30fc66231f0..01737e25443 100644 --- a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift +++ b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift @@ -261,18 +261,18 @@ extension Bookmarkv2 { let result = folder.bookmarkNode.children.map({ Bookmarkv2($0) }) return includeFolders ? result : result.filter({ $0.isFolder == false }) } - public static func byFrequency(query: String? = nil, _ completion: @escaping ([WebsitePresentable]) -> Void) { + + public static func byFrequency(query: String? = nil) -> [WebsitePresentable] { // Invalid query.. BraveCore doesn't store bookmarks based on last visited. // Any last visited bookmarks would show up in `History` anyway. // BraveCore automatically sorts them by date as well. guard let query = query, !query.isEmpty, let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { - return + return [] } - bookmarksAPI.search(withQuery: query, maxCount: 200, completion: { bookmarkResults in - completion(bookmarkResults.compactMap({ return !$0.isFolder ? Bookmarkv2($0) : nil })) - }) + return bookmarksAPI.search(withQuery: query, maxCount: 200) + .compactMap({ return !$0.isFolder ? Bookmarkv2($0) : nil }) } public func update(customTitle: String?, url: URL?) { From 41828f0ffefcd9678d26661ac75e6801a5ed931a Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Wed, 30 Jun 2021 11:22:59 -0400 Subject: [PATCH 29/43] Changes related to API usage --- Client/Frontend/Browser/FrequencyQuery.swift | 10 +++--- .../Sync/BraveCore/Bookmarks/Bookmarkv2.swift | 33 +++++++++---------- .../Sync/BraveCore/History/Historyv2.swift | 17 +++++----- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Client/Frontend/Browser/FrequencyQuery.swift b/Client/Frontend/Browser/FrequencyQuery.swift index 97c04f5fbe8..08e627b97ed 100644 --- a/Client/Frontend/Browser/FrequencyQuery.swift +++ b/Client/Frontend/Browser/FrequencyQuery.swift @@ -23,12 +23,12 @@ class FrequencyQuery { cancellable = DispatchWorkItem { // brave-core fetch can be slow over 200ms per call, // a cancellable serial queue is used for it. - let bookmarkSites = Bookmarkv2.byFrequency(query: query) - .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } - - let result = Set(historySites+bookmarkSites) - DispatchQueue.main.async { + let bookmarkSites = Bookmarkv2.byFrequency(query: query) + .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } + + let result = Set(historySites+bookmarkSites) + completion(result) } } diff --git a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift index 01737e25443..39ebd849c59 100644 --- a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift +++ b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift @@ -18,7 +18,8 @@ class Bookmarkv2: WebsitePresentable { private let bookmarkNode: BookmarkNode private var bookmarkFavIconObserver: BookmarkModelListener? private static var bookmarkModelLoadedObserver: BookmarkModelListener? - + private static let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI + init(_ bookmarkNode: BookmarkNode) { self.bookmarkNode = bookmarkNode } @@ -61,7 +62,7 @@ class Bookmarkv2: WebsitePresentable { } public var parent: Bookmarkv2? { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return nil } @@ -104,7 +105,7 @@ class Bookmarkv2: WebsitePresentable { } public func delete() { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return } @@ -117,7 +118,7 @@ class Bookmarkv2: WebsitePresentable { // If no folder was visited, returns the mobile bookmarks folder // If the root folder was visited, returns nil public static func lastVisitedFolder() -> Bookmarkv2? { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = self.bookmarksAPI else { return nil } @@ -149,7 +150,7 @@ class Bookmarkv2: WebsitePresentable { } public static func lastFolderPath() -> [Bookmarkv2] { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return [] } @@ -203,7 +204,7 @@ class BraveBookmarkFolder: Bookmarkv2 { extension Bookmarkv2 { public class func mobileNode() -> Bookmarkv2? { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return nil } @@ -214,7 +215,7 @@ extension Bookmarkv2 { } public class func addFolder(title: String, parentFolder: Bookmarkv2? = nil) { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return } @@ -226,7 +227,7 @@ extension Bookmarkv2 { } public class func add(url: URL, title: String?, parentFolder: Bookmarkv2? = nil) { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return } @@ -242,7 +243,7 @@ extension Bookmarkv2 { } public static func frc(parent: Bookmarkv2?) -> BookmarksV2FetchResultsController? { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return nil } @@ -250,7 +251,7 @@ extension Bookmarkv2 { } public static func foldersFrc(excludedFolder: Bookmarkv2? = nil) -> BookmarksV2FetchResultsController? { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return nil } @@ -266,8 +267,7 @@ extension Bookmarkv2 { // Invalid query.. BraveCore doesn't store bookmarks based on last visited. // Any last visited bookmarks would show up in `History` anyway. // BraveCore automatically sorts them by date as well. - guard let query = query, !query.isEmpty, - let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let query = query, !query.isEmpty, let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return [] } @@ -281,7 +281,7 @@ extension Bookmarkv2 { } public func updateWithNewLocation(customTitle: String?, url: URL?, location: Bookmarkv2?) { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return } @@ -306,8 +306,7 @@ extension Bookmarkv2 { public class func reorderBookmarks(frc: BookmarksV2FetchResultsController?, sourceIndexPath: IndexPath, destinationIndexPath: IndexPath) { - guard let frc = frc, - let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let frc = frc, let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return } @@ -345,7 +344,7 @@ extension Bookmarkv2 { } public func addFavIconObserver(_ observer: @escaping () -> Void) { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return } @@ -368,7 +367,7 @@ extension Bookmarkv2 { } public static func waitForBookmarkModelLoaded(_ completion: @escaping () -> Void) { - guard let bookmarksAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.bookmarksAPI else { + guard let bookmarksAPI = Bookmarkv2.bookmarksAPI else { return } diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index 61baa7d1beb..d227803020b 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -86,7 +86,8 @@ class Historyv2: WebsitePresentable { private let historyNode: HistoryNode private static var observer: HistoryServiceListener? - + private static let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI + private func fetchHistoryTimePeriod(visited: Date?) -> Section? { let todayOffset = 0 let yesterdayOffset = -1 @@ -125,7 +126,7 @@ class Historyv2: WebsitePresentable { extension Historyv2 { public class func add(url: URL, title: String, dateAdded: Date, isURLTyped: Bool = true) { - guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + guard let historyAPI = Historyv2.historyAPI else { return } @@ -134,7 +135,7 @@ extension Historyv2 { } public static func frc() -> HistoryV2FetchResultsController? { - guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + guard let historyAPI = Historyv2.historyAPI else { return nil } @@ -142,7 +143,7 @@ extension Historyv2 { } public func delete() { - guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + guard let historyAPI = Historyv2.historyAPI else { return } @@ -150,7 +151,7 @@ extension Historyv2 { } public class func deleteAll(_ completion: @escaping () -> Void) { - guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + guard let historyAPI = Historyv2.historyAPI else { return } @@ -160,7 +161,7 @@ extension Historyv2 { } public class func suffix(_ maxLength: Int, _ completion: @escaping ([Historyv2]) -> Void) { - guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + guard let historyAPI = Historyv2.historyAPI else { return } @@ -171,7 +172,7 @@ extension Historyv2 { public static func byFrequency(query: String? = nil, _ completion: @escaping ([WebsitePresentable]) -> Void) { guard let query = query, !query.isEmpty, - let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + let historyAPI = Historyv2.historyAPI else { return } @@ -196,7 +197,7 @@ extension Historyv2 { extension Historyv2 { public static func waitForHistoryServiceLoaded(_ completion: @escaping () -> Void) { - guard let historyAPI = (UIApplication.shared.delegate as? AppDelegate)?.braveCore?.historyAPI else { + guard let historyAPI = Historyv2.historyAPI else { return } From 6019d86aa7bfc712e3e07c93fe0ab72f1469786c Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 9 Jul 2021 13:51:17 -0400 Subject: [PATCH 30/43] Fixing string key localization problems --- BraveShared/BraveStrings.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BraveShared/BraveStrings.swift b/BraveShared/BraveStrings.swift index 810750def22..9e86cd9e1b2 100644 --- a/BraveShared/BraveStrings.swift +++ b/BraveShared/BraveStrings.swift @@ -2199,7 +2199,7 @@ extension Strings { value: "Manage what information you would like to sync between devices. These settings only affect this device.", comment: "Information Text underneath the toggles for enable/disable different sync types for the device") public static let syncSettingsTitle = - NSLocalizedString("sync.syncConfigurationInformationText", tableName: "BraveShared", bundle: .braveShared, + NSLocalizedString("sync.syncSettingsTitle", tableName: "BraveShared", bundle: .braveShared, value: "Sync Settings", comment: "Title for Sync Settings Toggle Header") } From 67674030d91bb94f06fb33d30404526a3a6283e7 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 9 Jul 2021 13:55:02 -0400 Subject: [PATCH 31/43] Reverting reportSponsoredImageBackgroundEvent change --- .../NewTabPageViewController.swift | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Client/Frontend/Browser/New Tab Page/NewTabPageViewController.swift b/Client/Frontend/Browser/New Tab Page/NewTabPageViewController.swift index 3cfb4b38906..a1427c7ed49 100644 --- a/Client/Frontend/Browser/New Tab Page/NewTabPageViewController.swift +++ b/Client/Frontend/Browser/New Tab Page/NewTabPageViewController.swift @@ -232,7 +232,7 @@ class NewTabPageViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) -// reportSponsoredImageBackgroundEvent(.viewed) + reportSponsoredImageBackgroundEvent(.viewed) presentNotification() } @@ -377,18 +377,18 @@ class NewTabPageViewController: UIViewController { backgroundView.imageConstraints?.landscapeCenter.update(offset: inset) } -// private func reportSponsoredImageBackgroundEvent(_ event: NewTabPageAdEventType) { -// guard let backgroundType = background.currentBackground?.type, -// case .withBrandLogo = backgroundType, -// let creativeInstanceId = background.currentBackground?.wallpaper.creativeInstanceId else { -// return -// } -// rewards.ads.reportNewTabPageAdEvent( -// background.wallpaperId.uuidString, -// creativeInstanceId: creativeInstanceId, -// eventType: event -// ) -// } + private func reportSponsoredImageBackgroundEvent(_ event: NewTabPageAdEventType) { + guard let backgroundType = background.currentBackground?.type, + case .withBrandLogo = backgroundType, + let creativeInstanceId = background.currentBackground?.wallpaper.creativeInstanceId else { + return + } + rewards.ads.reportNewTabPageAdEvent( + background.wallpaperId.uuidString, + creativeInstanceId: creativeInstanceId, + eventType: event + ) + } // MARK: - Notifications @@ -673,7 +673,7 @@ class NewTabPageViewController: UIViewController { UIImpactFeedbackGenerator(style: .medium).bzzt() delegate?.navigateToInput(logo.destinationUrl, inNewTab: false, switchingToPrivateMode: false) -// reportSponsoredImageBackgroundEvent(.clicked) + reportSponsoredImageBackgroundEvent(.clicked) } private func tappedQRCode(_ code: String) { From 143fe4d563fc83a0173c77f68aec4a28765ca4b4 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 9 Jul 2021 14:18:11 -0400 Subject: [PATCH 32/43] Request Fixes inside Migration Class --- Client/Application/Migration.swift | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Client/Application/Migration.swift b/Client/Application/Migration.swift index 7f352e090b4..a1927ca41c0 100644 --- a/Client/Application/Migration.swift +++ b/Client/Application/Migration.swift @@ -15,10 +15,10 @@ class Migration { private(set) public static var braveCoreSyncObjectsMigrator: BraveCoreMigrator? - private(set) public static var isChromiumMigrationCompleted: Bool = { + public static var isChromiumMigrationCompleted: Bool { return Preferences.Chromium.syncV2BookmarksMigrationCompleted.value && Preferences.Chromium.syncV2HistoryMigrationCompleted.value - }() + } static func launchMigrations(keyPrefix: String) { Preferences.migratePreferences(keyPrefix: keyPrefix) @@ -46,8 +46,10 @@ class Migration { NotificationCenter.default.addObserver( self, - selector: #selector(enableUserSelectedTypesForSync), name: NSNotification.Name(rawValue: BraveServiceStateObserver.coreServiceLoadedNotification), - object: nil) + selector: #selector(enableUserSelectedTypesForSync), + name: NSNotification.Name(rawValue: BraveServiceStateObserver.coreServiceLoadedNotification), + object: nil + ) } @objc private func enableUserSelectedTypesForSync() { From b76e1075ab95bc08fe453c5dd516bc94622a0a6d Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 9 Jul 2021 14:57:16 -0400 Subject: [PATCH 33/43] Code Syntax-Style changes and fixes + Removing unused code --- Client/Frontend/Browser/BrowserViewController.swift | 10 ++++------ .../History/HistoryServiceStateObserver.swift | 1 - Client/Frontend/Sync/BraveCore/History/Historyv2.swift | 6 ------ .../Sync/SyncSettingsTableViewController.swift | 6 +++--- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController.swift b/Client/Frontend/Browser/BrowserViewController.swift index 05949cccc8f..a384ac1747e 100644 --- a/Client/Frontend/Browser/BrowserViewController.swift +++ b/Client/Frontend/Browser/BrowserViewController.swift @@ -1230,12 +1230,10 @@ class BrowserViewController: UIViewController { // Disable any sort of privileged execution contexts // IE: The user must explicitly tap a bookmark they have saved. // Block all other contexts such as redirects, downloads, embed, linked, etc.. - if visitType == .bookmark { - if let webView = tab.webView, let code = url.bookmarkletCodeComponent { - webView.evaluateSafeJavaScript(functionName: code, sandboxed: false, asFunction: false) { _, error in - if let error = error { - log.error(error) - } + if visitType == .bookmark, let webView = tab.webView, let code = url.bookmarkletCodeComponent { + webView.evaluateSafeJavaScript(functionName: code, sandboxed: false, asFunction: false) { _, error in + if let error = error { + log.error(error) } } } diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift b/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift index a71c0267559..1177ee4a438 100644 --- a/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift +++ b/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift @@ -19,7 +19,6 @@ class HistoryServiceStateObserver: BraveServiceStateObserver, HistoryServiceObse init(_ listener: @escaping (StateChange) -> Void) { self.listener = listener - } func historyServiceLoaded() { diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index d227803020b..3d3f32670ae 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -12,12 +12,6 @@ import Shared private let log = Logger.browserLogger -struct Historyv2Section { - var title: String - - var numberOfObjects: Int -} - // A Lightweight wrapper around BraveCore history // with the same layout/interface as `History (from CoreData)` class Historyv2: WebsitePresentable { diff --git a/Client/Frontend/Sync/SyncSettingsTableViewController.swift b/Client/Frontend/Sync/SyncSettingsTableViewController.swift index 81f1dc72c67..92557566155 100644 --- a/Client/Frontend/Sync/SyncSettingsTableViewController.swift +++ b/Client/Frontend/Sync/SyncSettingsTableViewController.swift @@ -36,7 +36,7 @@ class SyncSettingsTableViewController: UITableViewController { self.updateDeviceList() - tableView.tableHeaderView = configureInformationView(with: Strings.syncSettingsHeader) + tableView.tableHeaderView = makeInformationTextView(with: Strings.syncSettingsHeader) } override func viewWillAppear(_ animated: Bool) { @@ -250,7 +250,7 @@ extension SyncSettingsTableViewController { override func tableView(_ tableView: UITableView, viewForFooterInSection sectionIndex: Int) -> UIView? { switch sectionIndex { case Sections.syncTypes.rawValue: - return configureInformationView(with: Strings.Sync.syncConfigurationInformationText) + return makeInformationTextView(with: Strings.Sync.syncConfigurationInformationText) default: return nil } @@ -332,7 +332,7 @@ extension SyncSettingsTableViewController { } } - private func configureInformationView(with info: String) -> UITextView { + private func makeInformationTextView(with info: String) -> UITextView { return UITextView().then { $0.text = info $0.textContainerInset = UIEdgeInsets(top: 16, left: 16, bottom: 0, right: 16) From 7fc37b174c7aced4a9ec1ed461ebc32f7f70b9a6 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Fri, 9 Jul 2021 15:39:38 -0400 Subject: [PATCH 34/43] OrderedDictionary is adde as a library for SPMLibraries --- Client.xcodeproj/project.pbxproj | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/Client.xcodeproj/project.pbxproj b/Client.xcodeproj/project.pbxproj index 400e68705d8..b03a7262f6a 100644 --- a/Client.xcodeproj/project.pbxproj +++ b/Client.xcodeproj/project.pbxproj @@ -446,6 +446,7 @@ 2F51767425E4024B00429692 /* PlaylistSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F51767325E4024B00429692 /* PlaylistSettingsViewController.swift */; }; 2F55443225913BD5000E4689 /* OpenSearchEngineButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F55443125913BD5000E4689 /* OpenSearchEngineButton.swift */; }; 2F5893C5265ED772002323D9 /* BrowserViewController+ProductNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F5893C4265ED772002323D9 /* BrowserViewController+ProductNotification.swift */; }; + 2F5B27D72698DBA8002BF5CF /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 2F5B27D62698DBA8002BF5CF /* OrderedCollections */; }; 2F676F6F260BA1B00048A1DB /* BlockingSummaryDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F676F6E260BA1B00048A1DB /* BlockingSummaryDataSource.swift */; }; 2F676FAD260BA4860048A1DB /* blocking-summary.json in Resources */ = {isa = PBXBuildFile; fileRef = 2F676FAC260BA4860048A1DB /* blocking-summary.json */; }; 2F6931B7260CFB3700ECEB38 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F6931B6260CFB3700ECEB38 /* IntentHandler.swift */; }; @@ -459,7 +460,6 @@ 2FA01E5D25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */; }; 2FA5A7582649CD9200740035 /* HistoryServiceStateObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FA5A7572649CD9200740035 /* HistoryServiceStateObserver.swift */; }; 2FB0E26C2653132500B722AF /* BraveServiceStateObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB0E26B2653132500B722AF /* BraveServiceStateObserver.swift */; }; - 2FB9C2A12587E742009DA1FE /* BrowserViewController+ProductNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */; }; 2FBCB169262784BF00F512D8 /* BrowserViewController+CoreMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */; }; 2FCAE2251ABB51F800877008 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FCAE21A1ABB51F800877008 /* Storage.framework */; }; 2FCAE2311ABB51F800877008 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FCAE21A1ABB51F800877008 /* Storage.framework */; }; @@ -470,7 +470,6 @@ 2FCAE2771ABB531100877008 /* SwiftData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCAE25B1ABB531100877008 /* SwiftData.swift */; }; 2FCAE2841ABB533A00877008 /* MockFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCAE2791ABB533A00877008 /* MockFiles.swift */; }; 2FCAE33E1ABB5F1800877008 /* Storage-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FCAE33D1ABB5F1800877008 /* Storage-Bridging-Header.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2FCE87D5264195EC00B98D7E /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 2FCE87D4264195EC00B98D7E /* OrderedCollections */; }; 2FD0E3AF2576C48A000C773B /* SchemePermissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD0E3AE2576C48A000C773B /* SchemePermissionTests.swift */; }; 2FD0E3D62577F327000C773B /* SearchSuggestionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD0E3D52577F327000C773B /* SearchSuggestionCell.swift */; }; 2FD1C60926385C6200E3C25F /* Historyv2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD1C60826385C6200E3C25F /* Historyv2.swift */; }; @@ -1964,7 +1963,6 @@ 2FA01E5C25F2C93800103D67 /* ShieldsActivityItemSourceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShieldsActivityItemSourceProvider.swift; sourceTree = ""; }; 2FA5A7572649CD9200740035 /* HistoryServiceStateObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryServiceStateObserver.swift; sourceTree = ""; }; 2FB0E26B2653132500B722AF /* BraveServiceStateObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BraveServiceStateObserver.swift; sourceTree = ""; }; - 2FB9C2A02587E742009DA1FE /* BrowserViewController+ProductNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+ProductNotification.swift"; sourceTree = ""; }; 2FBCB168262784BF00F512D8 /* BrowserViewController+CoreMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+CoreMigration.swift"; sourceTree = ""; }; 2FCAE21A1ABB51F800877008 /* Storage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Storage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2FCAE2241ABB51F800877008 /* StorageTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StorageTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2766,6 +2764,7 @@ 27756B0F25AD08FA00C129AF /* SDWebImage in Frameworks */, 277568F925ACF92400C129AF /* SwiftKeychainWrapper in Frameworks */, 27F4798C25AF94B0004922E4 /* YubiKit in Frameworks */, + 2F5B27D72698DBA8002BF5CF /* OrderedCollections in Frameworks */, 277568F325ACF92400C129AF /* Fuzi in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2819,7 +2818,6 @@ 27756A8325ACFFEB00C129AF /* pop.framework in Frameworks */, E6231C051B90A472005ABB0D /* libxml2.2.tbd in Frameworks */, E6231C011B90A44F005ABB0D /* libz.tbd in Frameworks */, - 2FCE87D5264195EC00B98D7E /* OrderedCollections in Frameworks */, 288A2D9D1AB8B3260023ABC3 /* Shared.framework in Frameworks */, 5DE7689920B3456E00FF5533 /* BraveShared.framework in Frameworks */, 2FCAE2311ABB51F800877008 /* Storage.framework in Frameworks */, @@ -4178,17 +4176,6 @@ path = ThirdParty; sourceTree = ""; }; - 2FFD2012260B914200E552A5 /* ProductNotifications */ = { - isa = PBXGroup; - children = ( - 2F5893C4265ED772002323D9 /* BrowserViewController+ProductNotification.swift */, - 2F676F6E260BA1B00048A1DB /* BlockingSummaryDataSource.swift */, - 2FE5B42A2580216700BFDDB8 /* ShareTrackersController.swift */, - 2F676FAC260BA4860048A1DB /* blocking-summary.json */, - ); - path = ProductNotifications; - sourceTree = ""; - }; 2FD1C5FA2638599100E3C25F /* Bookmarks */ = { isa = PBXGroup; children = ( @@ -4218,6 +4205,17 @@ path = History; sourceTree = ""; }; + 2FFD2012260B914200E552A5 /* ProductNotifications */ = { + isa = PBXGroup; + children = ( + 2F5893C4265ED772002323D9 /* BrowserViewController+ProductNotification.swift */, + 2F676F6E260BA1B00048A1DB /* BlockingSummaryDataSource.swift */, + 2FE5B42A2580216700BFDDB8 /* ShareTrackersController.swift */, + 2F676FAC260BA4860048A1DB /* blocking-summary.json */, + ); + path = ProductNotifications; + sourceTree = ""; + }; 392ED7D51D0AEEEE009D9B62 /* Accessors */ = { isa = PBXGroup; children = ( @@ -5829,6 +5827,7 @@ 27F4798B25AF94B0004922E4 /* YubiKit */, 27B68E5C25C88CA7002D0826 /* FeedKit */, 277046C12684CD2A001CB097 /* PanModal */, + 2F5B27D62698DBA8002BF5CF /* OrderedCollections */, ); productName = SPMLibraries; productReference = 277568D025ACF91500C129AF /* SPMLibraries.framework */; @@ -6096,7 +6095,6 @@ ); name = Client; packageProductDependencies = ( - 2FCE87D4264195EC00B98D7E /* OrderedCollections */, ); productName = Client; productReference = F84B21BE1A090F8100AAB793 /* Client.app */; @@ -13027,7 +13025,7 @@ package = 27F4798A25AF94B0004922E4 /* XCRemoteSwiftPackageReference "yubikit-ios" */; productName = YubiKit; }; - 2FCE87D4264195EC00B98D7E /* OrderedCollections */ = { + 2F5B27D62698DBA8002BF5CF /* OrderedCollections */ = { isa = XCSwiftPackageProductDependency; package = 2FCE87D3264195EC00B98D7E /* XCRemoteSwiftPackageReference "swift-collections" */; productName = OrderedCollections; From 2f760e7d71d4ba35cd4ebb272ebb5ff1c414ce7a Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 12 Jul 2021 11:00:59 -0400 Subject: [PATCH 35/43] Documentation and test around typedDisplayString is included --- Shared/Extensions/URLExtensions.swift | 3 +++ SharedTests/NSURLExtensionsTests.swift | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/Shared/Extensions/URLExtensions.swift b/Shared/Extensions/URLExtensions.swift index ec02373ea3a..8340f7aacc5 100644 --- a/Shared/Extensions/URLExtensions.swift +++ b/Shared/Extensions/URLExtensions.swift @@ -193,6 +193,9 @@ extension URL { } } + /// String suitable to detect the URL navigation type + /// This will return URL as a string without the scheme or ending "/" suffix limitation + /// This will be used as a key while storing navigation type of url before it is added to history public var typedDisplayString: String { var urlString = self.absoluteString diff --git a/SharedTests/NSURLExtensionsTests.swift b/SharedTests/NSURLExtensionsTests.swift index 583a3ba858c..2af47b400e4 100644 --- a/SharedTests/NSURLExtensionsTests.swift +++ b/SharedTests/NSURLExtensionsTests.swift @@ -695,4 +695,27 @@ class NSURLExtensionsTests: XCTestCase { XCTAssertFalse(URL(string: $0)?.isVideoSteamingSiteURL ?? false, "failed for \($0)") } } + + func testTypedDisplayString() { + let testURL1 = URL(string: "https://www.youtube.com") + let testURL2 = URL(string: "http://google.com") + let testURL3 = URL(string: "www.brave.com") + let testURL4 = URL(string: "http://brave.com/foo/") + let testURL5 = URL(string: "http://brave.com/foo") + + func checkDisplayURLString(testURL: URL?, displayString: String) { + if let actual = testURL?.typedDisplayString { + XCTAssertEqual(actual, displayString) + } else { + XCTFail("Actual url is nil") + } + } + + checkDisplayURLString(testURL: testURL1, displayString: "www.youtube.com") + checkDisplayURLString(testURL: testURL2, displayString: "google.com") + checkDisplayURLString(testURL: testURL3, displayString: "www.brave.com") + checkDisplayURLString(testURL: testURL4, displayString: "brave.com/foo") + checkDisplayURLString(testURL: testURL5, displayString: "brave.com/foo") + + } } From 3f51f6f6c8d3f4cf3ebe896aa3540f9970d044b8 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 12 Jul 2021 13:17:24 -0400 Subject: [PATCH 36/43] Notification Initializer Change and Observer loaded state tracked in one place. --- Client/Application/Migration.swift | 2 +- .../Bookmarks/BookmarkModelStateObserver.swift | 4 +--- .../Sync/BraveCore/BraveServiceStateObserver.swift | 10 +++++++--- .../History/HistoryServiceStateObserver.swift | 4 +--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Client/Application/Migration.swift b/Client/Application/Migration.swift index a1927ca41c0..d2dc30a5cdf 100644 --- a/Client/Application/Migration.swift +++ b/Client/Application/Migration.swift @@ -47,7 +47,7 @@ class Migration { NotificationCenter.default.addObserver( self, selector: #selector(enableUserSelectedTypesForSync), - name: NSNotification.Name(rawValue: BraveServiceStateObserver.coreServiceLoadedNotification), + name: BraveServiceStateObserver.coreServiceLoadedNotification, object: nil ) } diff --git a/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift index ed7e9590525..ddf15da4c3e 100644 --- a/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift +++ b/Client/Frontend/Sync/BraveCore/Bookmarks/BookmarkModelStateObserver.swift @@ -26,9 +26,7 @@ class BookmarkModelStateObserver: BraveServiceStateObserver, BookmarkModelObserv func bookmarkModelLoaded() { self.listener(.modelLoaded) - if !BraveServiceStateObserver.isServiceLoadStatePosted { - postServiceLoadedNotification() - } + postServiceLoadedNotification() } func bookmarkNodeChanged(_ bookmarkNode: BookmarkNode) { diff --git a/Client/Frontend/Sync/BraveCore/BraveServiceStateObserver.swift b/Client/Frontend/Sync/BraveCore/BraveServiceStateObserver.swift index 2941317567b..d0df1487353 100644 --- a/Client/Frontend/Sync/BraveCore/BraveServiceStateObserver.swift +++ b/Client/Frontend/Sync/BraveCore/BraveServiceStateObserver.swift @@ -9,15 +9,19 @@ class BraveServiceStateObserver: NSObject { // MARK: Static - static let coreServiceLoadedNotification = "BraveServiceStateDidLoaded" - + static let coreServiceLoadedNotification: Notification.Name = .init(rawValue: "BraveServiceStateDidLoaded") + static var isServiceLoadStatePosted = false // MARK: Private func postServiceLoadedNotification() { + guard !BraveServiceStateObserver.isServiceLoadStatePosted else { + return + } + NotificationCenter.default.post( - name: Notification.Name(rawValue: BraveServiceStateObserver.coreServiceLoadedNotification), + name: BraveServiceStateObserver.coreServiceLoadedNotification, object: nil) BraveServiceStateObserver.isServiceLoadStatePosted = true diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift b/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift index 1177ee4a438..251ff9073d0 100644 --- a/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift +++ b/Client/Frontend/Sync/BraveCore/History/HistoryServiceStateObserver.swift @@ -24,9 +24,7 @@ class HistoryServiceStateObserver: BraveServiceStateObserver, HistoryServiceObse func historyServiceLoaded() { listener(.serviceLoaded) - if !BraveServiceStateObserver.isServiceLoadStatePosted { - postServiceLoadedNotification() - } + postServiceLoadedNotification() } func historyServiceBeingDeleted() { From 8b9e0278fce817ad750de46982e06e17600faa35 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 12 Jul 2021 14:13:49 -0400 Subject: [PATCH 37/43] Migration Types removed for Sync and Error with description is added --- .../BrowserViewController+CoreMigration.swift | 50 ++++++++++--------- .../Sync/BraveCore/BraveCoreMigrator.swift | 28 +++++++---- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift index 4cf291fded6..56b8d4f4f64 100644 --- a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift +++ b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift @@ -19,11 +19,11 @@ extension BrowserViewController { func doSyncMigration() { // We stop ever attempting migration after 3 times. if Preferences.Chromium.syncV2ObjectMigrationCount.value < 3 { - self.migrateToSyncObjects { success, syncType in - if !success { + self.migrateToSyncObjects { error in + if let error = error { DispatchQueue.main.async { let alert = UIAlertController(title: Strings.Sync.v2MigrationErrorTitle, - message: syncType == .bookmarks ? Strings.Sync.v2MigrationErrorMessage : Strings.Sync.historyMigrationErrorMessage, + message: error.localizedDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: Strings.OKString, style: .default, handler: nil)) self.present(alert, animated: true) @@ -39,7 +39,7 @@ extension BrowserViewController { } } - private func migrateToSyncObjects(_ completion: @escaping (_ success: Bool, _ type: MigrationSyncTypes?) -> Void) { + private func migrateToSyncObjects(_ completion: @escaping ((MigrationError?) -> Void)) { let showInterstitialPage = { (url: URL?) -> Bool in guard let url = url else { log.error("Cannot open bookmarks page in new tab") @@ -49,29 +49,31 @@ extension BrowserViewController { return BookmarksInterstitialPageHandler.showBookmarksPage(tabManager: self.tabManager, url: url) } - Migration.braveCoreSyncObjectsMigrator?.migrate({ success, syncType in + + Migration.braveCoreSyncObjectsMigrator?.migrate({ error in Preferences.Chromium.syncV2ObjectMigrationCount.value += 1 - if !success { - switch syncType { - case .bookmarks: - guard let url = BraveCoreMigrator.datedBookmarksURL else { - completion(showInterstitialPage(BraveCoreMigrator.bookmarksURL), .bookmarks) - return - } - - Migration.braveCoreSyncObjectsMigrator?.exportBookmarks(to: url) { success in - if success { - completion(showInterstitialPage(url), .bookmarks) - } else { - completion(showInterstitialPage(BraveCoreMigrator.bookmarksURL), .bookmarks) - } + guard let error = error else { + completion(nil) + return + } + + switch error { + case .failedBookmarksMigration: + guard let url = BraveCoreMigrator.datedBookmarksURL else { + completion(showInterstitialPage(BraveCoreMigrator.bookmarksURL) ? nil : error) + return + } + + Migration.braveCoreSyncObjectsMigrator?.exportBookmarks(to: url) { success in + if success { + completion(showInterstitialPage(url) ? nil : error) + } else { + completion(showInterstitialPage(BraveCoreMigrator.bookmarksURL) ? nil : error) } - default: - completion(false, syncType) - } - } else { - completion(true, syncType) + } + default: + completion(error) } }) } diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 2da55387626..538bc3ae8f6 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -12,12 +12,20 @@ import CoreData private let log = Logger.browserLogger -// MARK: MigrationSyncTypes +// MARK: MigrationError -public enum MigrationSyncTypes { - case bookmarks - case history - case all +public enum MigrationError: LocalizedError { + case failedBookmarksMigration + case failedHistoryMigration + + public var errorDescription: String? { + switch self { + case .failedBookmarksMigration: + return Strings.Sync.v2MigrationErrorMessage + case .failedHistoryMigration: + return Strings.Sync.historyMigrationErrorMessage + } + } } class BraveCoreMigrator { @@ -105,11 +113,11 @@ class BraveCoreMigrator { _migrationObserver.observe(from: object, handler) } - public func migrate(_ completion: ((_ success: Bool, _ type: MigrationSyncTypes?) -> Void)? = nil) { + public func migrate(_ completion: ((MigrationError?) -> Void)? = nil) { // Check If Chromium Sync Objects Migration is complete (Bookmarks-History) if Migration.isChromiumMigrationCompleted { migrationObserver = .completed - completion?(true, .all) + completion?(nil) return } @@ -117,7 +125,7 @@ class BraveCoreMigrator { migrateBookmarkModels { [unowned self] success in guard success else { self.migrationObserver = .failed - completion?(false, .bookmarks) + completion?(.failedBookmarksMigration) return } @@ -126,12 +134,12 @@ class BraveCoreMigrator { migrateHistoryModels { [unowned self] success in guard success else { self.migrationObserver = .failed - completion?(false, .history) + completion?(.failedHistoryMigration) return } - completion?(true, .all) + completion?(nil) } } } From 6f98d052d107c74be90d15c386db89616b1f3a32 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 12 Jul 2021 14:50:13 -0400 Subject: [PATCH 38/43] Removing unnecessary blank spaces --- .../Sync/BrowserViewController+CoreMigration.swift | 1 - Client/Frontend/Browser/Tab.swift | 3 --- 2 files changed, 4 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift index 56b8d4f4f64..b31188e041e 100644 --- a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift +++ b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift @@ -49,7 +49,6 @@ extension BrowserViewController { return BookmarksInterstitialPageHandler.showBookmarksPage(tabManager: self.tabManager, url: url) } - Migration.braveCoreSyncObjectsMigrator?.migrate({ error in Preferences.Chromium.syncV2ObjectMigrationCount.value += 1 diff --git a/Client/Frontend/Browser/Tab.swift b/Client/Frontend/Browser/Tab.swift index 3f07bbe4211..bab42ed11ef 100644 --- a/Client/Frontend/Browser/Tab.swift +++ b/Client/Frontend/Browser/Tab.swift @@ -716,9 +716,6 @@ extension Tab { /// or when the fallback call should not happen at all. /// The website expects the iOS device to always call this method(blocks on it). func injectResults() { - - - DispatchQueue.main.async { // If the backup search results happen before the Brave Search loads // The method we pass data to is undefined. From bbe5c73132a0d683ff2ed250348731725510914e Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Mon, 12 Jul 2021 15:35:24 -0400 Subject: [PATCH 39/43] Changing typedSiplayString implementation using schemelessAbsoluteURLString --- Shared/Extensions/URLExtensions.swift | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Shared/Extensions/URLExtensions.swift b/Shared/Extensions/URLExtensions.swift index 8340f7aacc5..702bb01a5af 100644 --- a/Shared/Extensions/URLExtensions.swift +++ b/Shared/Extensions/URLExtensions.swift @@ -197,14 +197,8 @@ extension URL { /// This will return URL as a string without the scheme or ending "/" suffix limitation /// This will be used as a key while storing navigation type of url before it is added to history public var typedDisplayString: String { - var urlString = self.absoluteString + var urlString = self.schemelessAbsoluteString - if urlString.hasPrefix("http://") { - urlString = String(urlString[urlString.index(urlString.startIndex, offsetBy: 7)...]) - } else if urlString.hasPrefix("https://") { - urlString = String(urlString[urlString.index(urlString.startIndex, offsetBy: 8)...]) - } - if urlString.hasSuffix("/") { urlString.removeLast() } From 2546b2e528e3065d03036283a82ca4af24d465a7 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Thu, 15 Jul 2021 14:30:08 -0400 Subject: [PATCH 40/43] PR Comments with styling and nits --- .../BrowserViewController+CoreMigration.swift | 2 +- Client/Frontend/Browser/FrequencyQuery.swift | 2 +- .../Sync/BraveCore/BraveCoreMigrator.swift | 32 +++++++++---------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift index b31188e041e..7918a8fa600 100644 --- a/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift +++ b/Client/Frontend/Browser/BrowserViewController/Sync/BrowserViewController+CoreMigration.swift @@ -39,7 +39,7 @@ extension BrowserViewController { } } - private func migrateToSyncObjects(_ completion: @escaping ((MigrationError?) -> Void)) { + private func migrateToSyncObjects(_ completion: @escaping ((BraveCoreMigrator.MigrationError?) -> Void)) { let showInterstitialPage = { (url: URL?) -> Bool in guard let url = url else { log.error("Cannot open bookmarks page in new tab") diff --git a/Client/Frontend/Browser/FrequencyQuery.swift b/Client/Frontend/Browser/FrequencyQuery.swift index 08e627b97ed..2f8bc9f217b 100644 --- a/Client/Frontend/Browser/FrequencyQuery.swift +++ b/Client/Frontend/Browser/FrequencyQuery.swift @@ -27,7 +27,7 @@ class FrequencyQuery { let bookmarkSites = Bookmarkv2.byFrequency(query: query) .map { Site(url: $0.url ?? "", title: $0.title ?? "", bookmarked: true) } - let result = Set(historySites+bookmarkSites) + let result = Set(historySites + bookmarkSites) completion(result) } diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 538bc3ae8f6..399620d1aea 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -12,22 +12,6 @@ import CoreData private let log = Logger.browserLogger -// MARK: MigrationError - -public enum MigrationError: LocalizedError { - case failedBookmarksMigration - case failedHistoryMigration - - public var errorDescription: String? { - switch self { - case .failedBookmarksMigration: - return Strings.Sync.v2MigrationErrorMessage - case .failedHistoryMigration: - return Strings.Sync.historyMigrationErrorMessage - } - } -} - class BraveCoreMigrator { // MARK: Migration State @@ -39,6 +23,22 @@ class BraveCoreMigrator { case completed } + // MARK: MigrationError + + enum MigrationError: LocalizedError { + case failedBookmarksMigration + case failedHistoryMigration + + public var errorDescription: String? { + switch self { + case .failedBookmarksMigration: + return Strings.Sync.v2MigrationErrorMessage + case .failedHistoryMigration: + return Strings.Sync.historyMigrationErrorMessage + } + } + } + @Observable private(set) public var migrationObserver: MigrationState = .notStarted From 9c10dad084c09e869e51b403320acc5652b39dc2 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Wed, 21 Jul 2021 16:11:27 -0400 Subject: [PATCH 41/43] Fixing Rebase problems --- .../Menu/HistoryViewController.swift | 489 ++++++++++-------- 1 file changed, 283 insertions(+), 206 deletions(-) diff --git a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift index 3f055efa5e3..20d66e5d9f5 100644 --- a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift +++ b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift @@ -9,225 +9,302 @@ import Storage import Data import CoreData -private struct HistoryViewControllerUX { - static let welcomeScreenPadding: CGFloat = 15 - static let welcomeScreenItemTextColor = UIColor.gray - static let welcomeScreenItemWidth = 170 -} - class HistoryViewController: SiteTableViewController, ToolbarUrlActionsProtocol { - weak var toolbarUrlActionsDelegate: ToolbarUrlActionsDelegate? - fileprivate lazy var emptyStateOverlayView: UIView = self.createEmptyStateOverview() - var frc: NSFetchedResultsController? - + + weak var toolbarUrlActionsDelegate: ToolbarUrlActionsDelegate? + + private lazy var emptyStateOverlayView: UIView = createEmptyStateOverlayView() + + private let spinner = UIActivityIndicatorView().then { + $0.snp.makeConstraints { make in + make.size.equalTo(24) + } + $0.hidesWhenStopped = true + $0.isHidden = true + } + + var historyFRC: HistoryV2FetchResultsController? + + /// Certain bookmark actions are different in private browsing mode. let isPrivateBrowsing: Bool - - init(isPrivateBrowsing: Bool) { - self.isPrivateBrowsing = isPrivateBrowsing - - super.init(nibName: nil, bundle: nil) - - NotificationCenter.default.addObserver(self, selector: #selector(HistoryViewController.notificationReceived(_:)), name: .dynamicFontChanged, object: nil) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - deinit { - NotificationCenter.default.removeObserver(self, name: .dynamicFontChanged, object: nil) - } - - override func viewDidLoad() { - frc = History.frc() - frc!.delegate = self - super.viewDidLoad() - self.tableView.accessibilityIdentifier = "History List" - title = Strings.historyScreenTitle - - reloadData() - } - - @objc func notificationReceived(_ notification: Notification) { - switch notification.name { - case .dynamicFontChanged: - if emptyStateOverlayView.superview != nil { - emptyStateOverlayView.removeFromSuperview() - } - emptyStateOverlayView = createEmptyStateOverview() - default: - // no need to do anything at all - break - } - } - - override func reloadData() { - guard let frc = frc else { - return - } - - do { - try frc.performFetch() - } catch let error as NSError { - print(error.description) - } - - tableView.reloadData() - updateEmptyPanelState() - } - - fileprivate func updateEmptyPanelState() { - if frc?.fetchedObjects?.isEmpty == true { - if self.emptyStateOverlayView.superview == nil { - self.tableView.addSubview(self.emptyStateOverlayView) - self.emptyStateOverlayView.snp.makeConstraints { make -> Void in - make.edges.equalTo(self.tableView) - make.size.equalTo(self.view) - } - } - } else { - self.emptyStateOverlayView.removeFromSuperview() - } - } - - fileprivate func createEmptyStateOverview() -> UIView { - let overlayView = UIView() - overlayView.backgroundColor = .secondaryBraveBackground - - return overlayView - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = super.tableView(tableView, cellForRowAt: indexPath) - configureCell(cell, atIndexPath: indexPath) - return cell - } - - func configureCell(_ _cell: UITableViewCell, atIndexPath indexPath: IndexPath) { - guard let cell = _cell as? TwoLineTableViewCell else { return } - - if !tableView.isEditing { - cell.gestureRecognizers?.forEach { cell.removeGestureRecognizer($0) } - let lp = UILongPressGestureRecognizer(target: self, action: #selector(longPressedCell(_:))) - cell.addGestureRecognizer(lp) - } - - let site = frc!.object(at: indexPath) - cell.backgroundColor = .clear - cell.setLines(site.title, detailText: site.url) - - cell.imageView?.contentMode = .scaleAspectFit - cell.imageView?.image = FaviconFetcher.defaultFaviconImage - cell.imageView?.layer.borderColor = BraveUX.faviconBorderColor.cgColor - cell.imageView?.layer.borderWidth = BraveUX.faviconBorderWidth - cell.imageView?.layer.cornerRadius = 6 - cell.imageView?.layer.cornerCurve = .continuous - cell.imageView?.layer.masksToBounds = true - if let url = site.domain?.url?.asURL { - cell.imageView?.loadFavicon(for: url) - } else { - cell.imageView?.clearMonogramFavicon() - cell.imageView?.image = FaviconFetcher.defaultFaviconImage - } - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let site = frc?.object(at: indexPath) - - if let u = site?.url, let url = URL(string: u) { - dismiss(animated: true) { - // Donate Custom Intent Open History - if !self.isPrivateBrowsing { - ActivityShortcutManager.shared.donateCustomIntent(for: .openHistory, with: url.absoluteString) + + var isHistoryRefreshing = false + + init(isPrivateBrowsing: Bool) { + self.isPrivateBrowsing = isPrivateBrowsing + super.init(nibName: nil, bundle: nil) + + historyFRC = Historyv2.frc() + historyFRC?.delegate = self + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + tableView.accessibilityIdentifier = "History List" + title = Strings.historyScreenTitle + + navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "playlist_delete_item").template, style: .done, target: self, action: #selector(performDeleteAll)) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + refreshHistory() + } + + private func refreshHistory() { + guard !isHistoryRefreshing else { + return + } + + view.addSubview(spinner) + spinner.snp.makeConstraints { + $0.center.equalTo(view.snp.center) + } + spinner.startAnimating() + isHistoryRefreshing = true + + Historyv2.waitForHistoryServiceLoaded { [weak self] in + guard let self = self else { return } + + self.reloadData() { + self.isHistoryRefreshing = false + self.spinner.stopAnimating() + self.spinner.removeFromSuperview() + } + } + } + + private func reloadData(_ completion: @escaping () -> Void) { + // Recreate the frc if it was previously removed + if historyFRC == nil { + historyFRC = Historyv2.frc() + historyFRC?.delegate = self + } + + historyFRC?.performFetch { [weak self] in + guard let self = self else { return } + + self.tableView.reloadData() + self.updateEmptyPanelState() + + completion() + } + } + + fileprivate func createEmptyStateOverlayView() -> UIView { + let overlayView = UIView().then { + $0.backgroundColor = .secondaryBraveBackground + } + + let logoImageView = UIImageView(image: #imageLiteral(resourceName: "emptyHistory").template).then { + $0.tintColor = .braveLabel + } + + let welcomeLabel = UILabel().then { + $0.text = Strings.History.historyEmptyStateTitle + $0.textAlignment = .center + $0.font = DynamicFontHelper.defaultHelper.DeviceFontLight + $0.textColor = .braveLabel + $0.numberOfLines = 0 + $0.adjustsFontSizeToFitWidth = true + } + + overlayView.addSubview(logoImageView) + + logoImageView.snp.makeConstraints { make in + make.centerX.equalTo(overlayView) + make.size.equalTo(60) + // Sets proper top constraint for iPhone 6 in portait and for iPad. + make.centerY.equalTo(overlayView).offset(-180).priority(100) + // Sets proper top constraint for iPhone 4, 5 in portrait. + make.top.greaterThanOrEqualTo(overlayView).offset(50) + } + + overlayView.addSubview(welcomeLabel) + + welcomeLabel.snp.makeConstraints { make in + make.centerX.equalTo(overlayView) + make.top.equalTo(logoImageView.snp.bottom).offset(15) + make.width.equalTo(170) + } + + return overlayView + } + + fileprivate func updateEmptyPanelState() { + if historyFRC?.fetchedObjectsCount == 0 { + if emptyStateOverlayView.superview == nil { + tableView.addSubview(emptyStateOverlayView) + emptyStateOverlayView.snp.makeConstraints { make -> Void in + make.edges.equalTo(tableView) + make.size.equalTo(view) + } + } + } else { + emptyStateOverlayView.removeFromSuperview() + } + } + + @objc private func performDeleteAll() { + let style: UIAlertController.Style = UIDevice.current.userInterfaceIdiom == .pad ? .alert : .actionSheet + let alert = UIAlertController( + title: Strings.History.historyClearAlertTitle, message: Strings.History.historyClearAlertDescription, preferredStyle: style) + + alert.addAction(UIAlertAction(title: Strings.History.historyClearActionTitle, style: .destructive, handler: { _ in + DispatchQueue.main.async { + Historyv2.deleteAll { [weak self] in + self?.refreshHistory() + } } + })) + alert.addAction(UIAlertAction(title: Strings.cancelButtonTitle, style: .cancel, handler: nil)) + + present(alert, animated: true, completion: nil) + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = super.tableView(tableView, cellForRowAt: indexPath) + configureCell(cell, atIndexPath: indexPath) + + return cell + } + + func configureCell(_ cell: UITableViewCell, atIndexPath indexPath: IndexPath) { + guard let cell = cell as? TwoLineTableViewCell else { return } + + if !tableView.isEditing { + cell.gestureRecognizers?.forEach { cell.removeGestureRecognizer($0) } + cell.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(longPressedCell(_:)))) + } + + guard let historyItem = historyFRC?.object(at: indexPath) else { return } + + cell.do { + $0.backgroundColor = UIColor.clear + $0.setLines(historyItem.title, detailText: historyItem.url) + + $0.imageView?.contentMode = .scaleAspectFit + $0.imageView?.image = FaviconFetcher.defaultFaviconImage + $0.imageView?.layer.borderColor = BraveUX.faviconBorderColor.cgColor + $0.imageView?.layer.borderWidth = BraveUX.faviconBorderWidth + $0.imageView?.layer.cornerRadius = 6 + $0.imageView?.layer.masksToBounds = true - self.toolbarUrlActionsDelegate?.select(url: url, isBookmark: false) + if let url = historyItem.domain?.asURL { + cell.imageView?.loadFavicon(for: url) + } else { + cell.imageView?.clearMonogramFavicon() + cell.imageView?.image = FaviconFetcher.defaultFaviconImage + } } } - tableView.deselectRow(at: indexPath, animated: true) - } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + guard let historyItem = historyFRC?.object(at: indexPath) else { return } + + if let historyURL = historyItem.url, let url = URL(string: historyURL) { + dismiss(animated: true) { + self.toolbarUrlActionsDelegate?.select(url: url, visitType: .typed) + } + } + + tableView.deselectRow(at: indexPath, animated: true) + } @objc private func longPressedCell(_ gesture: UILongPressGestureRecognizer) { guard gesture.state == .began, - let cell = gesture.view as? UITableViewCell, - let indexPath = tableView.indexPath(for: cell), - let urlString = frc?.object(at: indexPath).url else { - return + let cell = gesture.view as? UITableViewCell, + let indexPath = tableView.indexPath(for: cell), + let urlString = historyFRC?.object(at: indexPath)?.url else { + return } presentLongPressActions(gesture, urlString: urlString, isPrivateBrowsing: isPrivateBrowsing) } - - func numberOfSections(in tableView: UITableView) -> Int { - return frc?.sections?.count ?? 0 - } - - func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - guard let sections = frc?.sections else { return nil } - return sections.indices ~= section ? sections[section].name : nil - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - guard let sections = frc?.sections else { return 0 } - return sections.indices ~= section ? sections[section].numberOfObjects : 0 - } - - func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { - if editingStyle == UITableViewCell.EditingStyle.delete { - if let obj = self.frc?.object(at: indexPath) { - obj.delete() - } - } - } + + func numberOfSections(in tableView: UITableView) -> Int { + return historyFRC?.sectionCount ?? 0 + } + + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return historyFRC?.titleHeader(for: section) + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return historyFRC?.objectCount(for: section) ?? 0 + } + + func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { + switch editingStyle { + case .delete: + guard let historyItem = historyFRC?.object(at: indexPath) else { return } + historyItem.delete() + + refreshHistory() + default: + break + } + } } -extension HistoryViewController: NSFetchedResultsControllerDelegate { - func controllerWillChangeContent(_ controller: NSFetchedResultsController) { - tableView.beginUpdates() - } - - func controllerDidChangeContent(_ controller: NSFetchedResultsController) { - tableView.endUpdates() - } - - func controller(_ controller: NSFetchedResultsController, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) { - switch type { - case .insert: - let sectionIndexSet = IndexSet(integer: sectionIndex) - self.tableView.insertSections(sectionIndexSet, with: .fade) - case .delete: - let sectionIndexSet = IndexSet(integer: sectionIndex) - self.tableView.deleteSections(sectionIndexSet, with: .fade) - default: break - } - } - - func controller(_ controller: NSFetchedResultsController, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { - switch type { - case .insert: - if let indexPath = newIndexPath { - tableView.insertRows(at: [indexPath], with: .automatic) - } - case .delete: - if let indexPath = indexPath { - tableView.deleteRows(at: [indexPath], with: .automatic) - } - case .update: - if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) { - configureCell(cell, atIndexPath: indexPath) - } - case .move: - if let indexPath = indexPath { - tableView.deleteRows(at: [indexPath], with: .automatic) - } - - if let newIndexPath = newIndexPath { - tableView.insertRows(at: [newIndexPath], with: .automatic) - } - @unknown default: - assertionFailure() - } - updateEmptyPanelState() - } +// MARK: - HistoryV2FetchResultsDelegate +extension HistoryViewController: HistoryV2FetchResultsDelegate { + + func controllerWillChangeContent(_ controller: HistoryV2FetchResultsController) { + tableView.beginUpdates() + } + + func controllerDidChangeContent(_ controller: HistoryV2FetchResultsController) { + tableView.endUpdates() + } + + func controller(_ controller: HistoryV2FetchResultsController, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { + switch type { + case .insert: + if let indexPath = newIndexPath { + tableView.insertRows(at: [indexPath], with: .automatic) + } + case .delete: + if let indexPath = indexPath { + tableView.deleteRows(at: [indexPath], with: .automatic) + } + case .update: + if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) { + configureCell(cell, atIndexPath: indexPath) + } + case .move: + if let indexPath = indexPath { + tableView.deleteRows(at: [indexPath], with: .automatic) + } + + if let newIndexPath = newIndexPath { + tableView.insertRows(at: [newIndexPath], with: .automatic) + } + @unknown default: + assertionFailure() + } + updateEmptyPanelState() + } + + func controller(_ controller: HistoryV2FetchResultsController, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) { + switch type { + case .insert: + let sectionIndexSet = IndexSet(integer: sectionIndex) + self.tableView.insertSections(sectionIndexSet, with: .fade) + case .delete: + let sectionIndexSet = IndexSet(integer: sectionIndex) + self.tableView.deleteSections(sectionIndexSet, with: .fade) + default: break + } + } + + func controllerDidReloadContents(_ controller: HistoryV2FetchResultsController) { + refreshHistory() + } } - From 2f678534ce34039a3b6477a8bfa14dcef4376b33 Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 27 Jul 2021 12:30:19 -0400 Subject: [PATCH 42/43] Pull Request Comments are addressed Fetch limit is changed to 200 --- .../BrowserViewController+ReaderMode.swift | 16 ++------ .../Menu/HistoryViewController.swift | 37 +++++++++---------- .../Sync/BraveCore/Bookmarks/Bookmarkv2.swift | 1 - .../BraveCore/History/HistoryFetchers.swift | 2 +- .../Sync/BraveCore/History/Historyv2.swift | 2 +- 5 files changed, 24 insertions(+), 34 deletions(-) diff --git a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift index acc8de884a5..ad9d950b515 100644 --- a/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift +++ b/Client/Frontend/Browser/BrowserViewController/BrowserViewController+ReaderMode.swift @@ -11,20 +11,12 @@ import Storage enum VisitType: Int { case unknown - /** - * This transition type means the user followed a link and got a new toplevel - * window. - */ + /// Transition type where user followed a link and got a new top-level window case link - - /** - * This transition type means that the user typed the page's URL in the - * URL bar or selected it from URL bar autocomplete results. - */ + /// Transition type where user typed the page's URL in the URL bar or selected it from URL bar autocomplete results. case typed - /** - * This transition type means that user opened a link from bookmarks. - */ + + /// Transition type where user opened a link from bookmarks. case bookmark case download } diff --git a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift index 20d66e5d9f5..a04d99adf5a 100644 --- a/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift +++ b/Client/Frontend/Browser/Toolbars/BottomToolbar/Menu/HistoryViewController.swift @@ -58,24 +58,22 @@ class HistoryViewController: SiteTableViewController, ToolbarUrlActionsProtocol } private func refreshHistory() { - guard !isHistoryRefreshing else { - return - } - - view.addSubview(spinner) - spinner.snp.makeConstraints { - $0.center.equalTo(view.snp.center) - } - spinner.startAnimating() - isHistoryRefreshing = true + if !isHistoryRefreshing { + view.addSubview(spinner) + spinner.snp.makeConstraints { + $0.center.equalTo(view.snp.center) + } + spinner.startAnimating() + isHistoryRefreshing = true - Historyv2.waitForHistoryServiceLoaded { [weak self] in - guard let self = self else { return } - - self.reloadData() { - self.isHistoryRefreshing = false - self.spinner.stopAnimating() - self.spinner.removeFromSuperview() + Historyv2.waitForHistoryServiceLoaded { [weak self] in + guard let self = self else { return } + + self.reloadData() { + self.isHistoryRefreshing = false + self.spinner.stopAnimating() + self.spinner.removeFromSuperview() + } } } } @@ -140,10 +138,10 @@ class HistoryViewController: SiteTableViewController, ToolbarUrlActionsProtocol fileprivate func updateEmptyPanelState() { if historyFRC?.fetchedObjectsCount == 0 { if emptyStateOverlayView.superview == nil { - tableView.addSubview(emptyStateOverlayView) + view.addSubview(emptyStateOverlayView) + view.bringSubviewToFront(emptyStateOverlayView) emptyStateOverlayView.snp.makeConstraints { make -> Void in make.edges.equalTo(tableView) - make.size.equalTo(view) } } } else { @@ -194,6 +192,7 @@ class HistoryViewController: SiteTableViewController, ToolbarUrlActionsProtocol $0.imageView?.layer.borderColor = BraveUX.faviconBorderColor.cgColor $0.imageView?.layer.borderWidth = BraveUX.faviconBorderWidth $0.imageView?.layer.cornerRadius = 6 + $0.imageView?.layer.cornerCurve = .continuous $0.imageView?.layer.masksToBounds = true if let url = historyItem.domain?.asURL { diff --git a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift index 39ebd849c59..020db05ba5c 100644 --- a/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift +++ b/Client/Frontend/Sync/BraveCore/Bookmarks/Bookmarkv2.swift @@ -376,7 +376,6 @@ extension Bookmarkv2 { completion() } } else { - //var observer: BookmarkModelListener? bookmarkModelLoadedObserver = bookmarksAPI.add(BookmarkModelStateObserver({ if case .modelLoaded = $0 { bookmarkModelLoadedObserver?.destroy() diff --git a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift index b5e96fba3c3..43657a3c75f 100644 --- a/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift +++ b/Client/Frontend/Sync/BraveCore/History/HistoryFetchers.swift @@ -85,7 +85,7 @@ class Historyv2Fetcher: NSObject, HistoryV2FetchResultsController { func performFetch(_ completion: @escaping () -> Void) { clearHistoryData() - historyAPI?.search(withQuery: "", maxCount: 0, completion: { [weak self] historyNodeList in + historyAPI?.search(withQuery: "", maxCount: 200, completion: { [weak self] historyNodeList in guard let self = self else { return } self.historyList = historyNodeList.map { [unowned self] historyNode in diff --git a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift index 3d3f32670ae..4204e5eff3b 100644 --- a/Client/Frontend/Sync/BraveCore/History/Historyv2.swift +++ b/Client/Frontend/Sync/BraveCore/History/Historyv2.swift @@ -24,7 +24,7 @@ class Historyv2: WebsitePresentable { case yesterday /// History happened between yesterday and end of this week case lastWeek - /// History happaned + /// History happened between end of this week and end of this month case thisMonth /// The list of titles time period From 1779d082d483a8297c99d98c8cf5d738ef101dfe Mon Sep 17 00:00:00 2001 From: Soner Yuksel Date: Tue, 27 Jul 2021 14:40:02 -0400 Subject: [PATCH 43/43] History Fetch updated method name and added a documentation comment that it fetches last month only --- Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift | 2 +- Data/models/History.swift | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift index 399620d1aea..a0dd08d443e 100644 --- a/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift +++ b/Client/Frontend/Sync/BraveCore/BraveCoreMigrator.swift @@ -307,7 +307,7 @@ extension BraveCoreMigrator { DataController.performOnMainContext { context in var didSucceed = true - for history in History.fetchAllHistory(context) { + for history in History.fetchMigrationHistory(context) { if self.migrateChromiumHistory(context: context, history: history) { history.delete() } else { diff --git a/Data/models/History.swift b/Data/models/History.swift index 66c71e52dad..c75a39ac014 100644 --- a/Data/models/History.swift +++ b/Data/models/History.swift @@ -111,9 +111,15 @@ public final class History: NSManagedObject, WebsitePresentable, CRUD { return all(where: predicate, fetchLimit: 100, context: DataController.viewContext) ?? [] } - public class func fetchAllHistory(_ context: NSManagedObjectContext? = nil, visitedAscending: Bool = false) -> [History] { + /// Fetching the History items for migration + /// The last month's data is being displayed to user + /// so data in this period data fetched from old history for migration + /// - Parameters: + /// - context: Managed Object Context + /// - Returns: Return old history items from core data + public class func fetchMigrationHistory(_ context: NSManagedObjectContext? = nil) -> [History] { let predicate = NSPredicate(format: "visitedOn >= %@", History.thisMonth as CVarArg) - let sortDescriptors = [NSSortDescriptor(key: "visitedOn", ascending: visitedAscending)] + let sortDescriptors = [NSSortDescriptor(key: "visitedOn", ascending: false)] return all(where: predicate, sortDescriptors: sortDescriptors, context: context ?? DataController.viewContext) ?? [] }