Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new tab page low hanging fruit #491

Merged
merged 10 commits into from
Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,8 @@
B63ED0E026AFE32F00A9DAD1 /* GeolocationProviderMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B63ED0DF26AFE32F00A9DAD1 /* GeolocationProviderMock.swift */; };
B63ED0E326B3E7FA00A9DAD1 /* CLLocationManagerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = B63ED0E226B3E7FA00A9DAD1 /* CLLocationManagerMock.swift */; };
B63ED0E526BB8FB900A9DAD1 /* SharingMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = B63ED0E426BB8FB900A9DAD1 /* SharingMenu.swift */; };
B643BF1427ABF772000BACEC /* NSWorkspaceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B643BF1327ABF772000BACEC /* NSWorkspaceExtension.swift */; };
B642738227B65BAC0005DFD1 /* SecureVaultErrorReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B642738127B65BAC0005DFD1 /* SecureVaultErrorReporter.swift */; };
B643BF1427ABF772000BACEC /* NSWorkspaceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B643BF1327ABF772000BACEC /* NSWorkspaceExtension.swift */; };
B64C84DE2692D7400048FEBE /* PermissionAuthorization.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B64C84DD2692D7400048FEBE /* PermissionAuthorization.storyboard */; };
B64C84E32692DC9F0048FEBE /* PermissionAuthorizationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64C84E22692DC9F0048FEBE /* PermissionAuthorizationViewController.swift */; };
B64C84EB2692DD650048FEBE /* PermissionAuthorizationPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = B64C84EA2692DD650048FEBE /* PermissionAuthorizationPopover.swift */; };
Expand Down Expand Up @@ -1053,6 +1053,7 @@
85F1B0C825EF9759004792B6 /* URLEventHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLEventHandlerTests.swift; sourceTree = "<group>"; };
85F487B4276A8F2E003CE668 /* OnboardingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTests.swift; sourceTree = "<group>"; };
85F69B3B25EDE81F00978E59 /* URLExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtensionTests.swift; sourceTree = "<group>"; };
85F91D9327F47BC40096B1C8 /* History 5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "History 5.xcdatamodel"; sourceTree = "<group>"; };
9812D894276CEDA5004B6181 /* ContentBlockerRulesLists.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBlockerRulesLists.swift; sourceTree = "<group>"; };
9826B09F2747DF3D0092F683 /* ContentBlocking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentBlocking.swift; sourceTree = "<group>"; };
9826B0A12747DFEB0092F683 /* AppPrivacyConfigurationDataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPrivacyConfigurationDataProvider.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1286,8 +1287,8 @@
B63ED0DF26AFE32F00A9DAD1 /* GeolocationProviderMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeolocationProviderMock.swift; sourceTree = "<group>"; };
B63ED0E226B3E7FA00A9DAD1 /* CLLocationManagerMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CLLocationManagerMock.swift; sourceTree = "<group>"; };
B63ED0E426BB8FB900A9DAD1 /* SharingMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingMenu.swift; sourceTree = "<group>"; };
B643BF1327ABF772000BACEC /* NSWorkspaceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWorkspaceExtension.swift; sourceTree = "<group>"; };
B642738127B65BAC0005DFD1 /* SecureVaultErrorReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureVaultErrorReporter.swift; sourceTree = "<group>"; };
B643BF1327ABF772000BACEC /* NSWorkspaceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSWorkspaceExtension.swift; sourceTree = "<group>"; };
B64C84DD2692D7400048FEBE /* PermissionAuthorization.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = PermissionAuthorization.storyboard; sourceTree = "<group>"; };
B64C84E22692DC9F0048FEBE /* PermissionAuthorizationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionAuthorizationViewController.swift; sourceTree = "<group>"; };
B64C84EA2692DD650048FEBE /* PermissionAuthorizationPopover.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionAuthorizationPopover.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -5544,12 +5545,13 @@
AAE75278263B046100B973F8 /* History.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
85F91D9327F47BC40096B1C8 /* History 5.xcdatamodel */,
85589E9227BFBBD60038AD11 /* History 4.xcdatamodel */,
AAC6BBEE27AC151D0006DCC2 /* History 3.xcdatamodel */,
AA7DE8E026A9BD000012B490 /* History 2.xcdatamodel */,
AAE75279263B046100B973F8 /* History.xcdatamodel */,
);
currentVersion = 85589E9227BFBBD60038AD11 /* History 4.xcdatamodel */;
currentVersion = 85F91D9327F47BC40096B1C8 /* History 5.xcdatamodel */;
path = History.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
2 changes: 2 additions & 0 deletions DuckDuckGo/Browser Tab/Model/Tab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,8 @@ extension Tab: ContentBlockerRulesUserScriptDelegate {
extension HistoryCoordinating {

func addDetectedTracker(_ tracker: DetectedTracker, onURL url: URL, contentBlocking: ContentBlocking = ContentBlocking.shared) {
trackerFound(onURL: url)

guard tracker.blocked,
let domain = tracker.domain,
let entityName = contentBlocking.entityName(forDomain: domain) else { return }
Expand Down
2 changes: 2 additions & 0 deletions DuckDuckGo/Common/Localizables/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,8 @@ struct UserText {

static let homePageEmptyStateItemTitle = NSLocalizedString("home.page.empty.state.item.title", value: "Recently visited sites appear here", comment: "")
static let homePageEmptyStateItemMessage = NSLocalizedString("home.page.empty.state.item.message", value: "Keep browsing to see how many trackers were blocked", comment: "")
static let homePageNoTrackersFound = NSLocalizedString("home.page.no.trackers.found", value: "No trackers found", comment: "")
static let homePageNoTrackersBlocked = NSLocalizedString("home.page.no.trackers.blocked", value: "No trackers blocked", comment: "")

static let tooltipAddToFavorites = NSLocalizedString("tooltip.addToFavorites", value: "Add to Favorites", comment: "Tooltip for add to favorites button")
static let tooltipBurn = NSLocalizedString("tooltip.burn", value: "Burn History and Site Data", comment: "Tooltip for burn button")
Expand Down
2 changes: 2 additions & 0 deletions DuckDuckGo/Common/Utilities/UserDefaultsWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public struct UserDefaultsWrapper<T> {
case onboardingFinished = "onboarding.finished"

case homePageShowPagesOnHover = "home.page.show.pages.on.hover"
case homePageShowAllFavorites = "home.page.show.all.favorites"
case homePageShowPageTitles = "home.page.show.page.titles"
}

enum RemovedKeys: String, CaseIterable {
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/Common/View/SwiftUI/FaviconView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct FaviconView: View {
}

func refreshImage() {
let image = faviconManagement.getCachedFavicon(for: domain, sizeCategory: .small)?.image
let image = faviconManagement.getCachedFavicon(for: domain, sizeCategory: .medium)?.image
if image?.size.isSmaller(than: CGSize(width: 16, height: 16)) == false {
self.image = image
}
Expand Down
18 changes: 18 additions & 0 deletions DuckDuckGo/History/Model/HistoryCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ protocol HistoryCoordinating: AnyObject {

func addVisit(of url: URL)
func addBlockedTracker(entityName: String, onURL url: URL)
func trackerFound(onURL: URL)
func updateTitleIfNeeded(title: String, url: URL)
func markFailedToLoadUrl(_ url: URL)
func title(for url: URL) -> String?
Expand Down Expand Up @@ -105,6 +106,23 @@ final class HistoryCoordinator: HistoryCoordinating {
}
}

func trackerFound(onURL url: URL) {
queue.async(flags: .barrier) { [weak self] in
guard let historyDictionary = self?.historyDictionary else {
os_log("Add tracker to %s ignored, no history", log: .history, url.absoluteString)
return
}

guard var entry = historyDictionary[url] else {
os_log("Add tracker to %s ignored, no entry", log: .history, url.absoluteString)
return
}

entry.trackersFound = true
self?.save(entry: entry)
}
}

func updateTitleIfNeeded(title: String, url: URL) {
queue.async(flags: .barrier) { [weak self] in
guard let historyDictionary = self?.historyDictionary else { return }
Expand Down
4 changes: 3 additions & 1 deletion DuckDuckGo/History/Model/HistoryEntry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct HistoryEntry {
var failedToLoad: Bool
var numberOfTrackersBlocked: Int
var blockedTrackingEntities: Set<String>
var trackersFound: Bool

mutating func addVisit() {
numberOfVisits += 1
Expand All @@ -54,7 +55,8 @@ extension HistoryEntry {
lastVisit: Date.startOfMinuteNow,
failedToLoad: false,
numberOfTrackersBlocked: 0,
blockedTrackingEntities: Set<String>())
blockedTrackingEntities: Set<String>(),
trackersFound: false)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>History 4.xcdatamodel</string>
<string>History 5.xcdatamodel</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21D62" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="HistoryEntryManagedObject" representedClassName="HistoryEntryManagedObject" syncable="YES" codeGenerationType="class">
<attribute name="blockedTrackingEntities" optional="YES" attributeType="String"/>
<attribute name="failedToLoad" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="lastVisit" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="numberOfTrackersBlocked" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="numberOfVisits" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="titleEncrypted" optional="YES" attributeType="Transformable" valueTransformerName="NSStringTransformer"/>
<attribute name="trackersFound" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="urlEncrypted" attributeType="Transformable" valueTransformerName="NSURLTransformer"/>
</entity>
<elements>
<element name="HistoryEntryManagedObject" positionX="-63" positionY="-18" width="128" height="164"/>
</elements>
</model>
4 changes: 3 additions & 1 deletion DuckDuckGo/History/Services/HistoryStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ fileprivate extension HistoryEntry {
lastVisit: lastVisit,
failedToLoad: historyMO.failedToLoad,
numberOfTrackersBlocked: Int(numberOfTrackersBlocked),
blockedTrackingEntities: Set<String>(blockedTrackingEntities.components(separatedBy: "|")))
blockedTrackingEntities: Set<String>(blockedTrackingEntities.components(separatedBy: "|")),
trackersFound: historyMO.trackersFound)
}

}
Expand All @@ -245,6 +246,7 @@ fileprivate extension HistoryEntryManagedObject {
failedToLoad = entry.failedToLoad
numberOfTrackersBlocked = Int64(entry.numberOfTrackersBlocked)
blockedTrackingEntities = entry.blockedTrackingEntities.isEmpty ? "" : entry.blockedTrackingEntities.joined(separator: "|")
trackersFound = entry.trackersFound
}

}
10 changes: 10 additions & 0 deletions DuckDuckGo/Home Page/Model/HomePageFavoritesModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ extension HomePage.Models {

}

@UserDefaultsWrapper(key: .homePageShowAllFavorites, defaultValue: false)
private static var showAllFavoritesSetting: Bool

@Published var showAllFavorites: Bool {
didSet {
Self.showAllFavoritesSetting = showAllFavorites
}
}

@Published var favorites: [Bookmark] = [] {
didSet {
var favorites = self.favorites.map { FavoriteModel(id: $0.id, favoriteType: .bookmark($0)) }
Expand All @@ -69,6 +78,7 @@ extension HomePage.Models {
remove: @escaping (Bookmark) -> Void,
addEdit: @escaping (Bookmark?) -> Void) {

self.showAllFavorites = Self.showAllFavoritesSetting
self.open = open
self.remove = remove
self.addEdit = addEdit
Expand Down
19 changes: 18 additions & 1 deletion DuckDuckGo/Home Page/Model/HomePageRecentlyVisitedModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,18 @@ final class RecentlyVisitedPageModel: ObservableObject {
self.actualTitle = actualTitle
self.url = url
self.visited = visited
self.displayTitle = actualTitle ?? "" // Default, but might change

// This gets fixed in the parent model, when iterating over history items
self.displayTitle = actualTitle ?? ""
}

}

final class RecentlyVisitedSiteModel: ObservableObject {

@UserDefaultsWrapper(key: .homePageShowPageTitles, defaultValue: false)
private var showTitlesForPagesSetting: Bool

let maxPageListSize = 10

let domain: String
Expand All @@ -145,6 +150,7 @@ final class RecentlyVisitedSiteModel: ObservableObject {
@Published var blockedEntities = [String]()
@Published var pages = [RecentlyVisitedPageModel]()
@Published var numberOfTrackersBlocked = 0
@Published var trackersFound = false

init(domain: String, bookmarkManager: BookmarkManager = LocalBookmarkManager.shared) {
self.domain = domain
Expand All @@ -162,6 +168,10 @@ final class RecentlyVisitedSiteModel: ObservableObject {
func addPage(fromHistory entry: HistoryEntry, bookmarkManager: BookmarkManager = LocalBookmarkManager.shared) {
numberOfTrackersBlocked += entry.numberOfTrackersBlocked

if entry.trackersFound {
trackersFound = true
}

// Skip root URLs and non-search DDG urls
guard !entry.url.isRoot || (entry.url.isDuckDuckGo && !entry.url.isDuckDuckGoSearch) else { return }

Expand All @@ -185,6 +195,13 @@ final class RecentlyVisitedSiteModel: ObservableObject {
urlsToRemove.append($0.url)
}

} else if !showTitlesForPagesSetting {

$0.displayTitle = $0.url.absoluteString
.drop(prefix: "https://")
.drop(prefix: "http://")
.drop(prefix: $0.url.host ?? "")

} else if $0.actualTitle?.isEmpty ?? true { // Blank titles

$0.displayTitle = $0.url.path
Expand Down
39 changes: 25 additions & 14 deletions DuckDuckGo/Home Page/View/FavoritesView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ struct Favorites: View {

@EnvironmentObject var model: HomePage.Models.FavoritesModel

@State var isExpanded = false
@State var isHovering = false

var rowIndices: Range<Int> {
model.showAllFavorites ? model.rows.indices : model.rows.indices.prefix(HomePage.favoritesRowCountWhenCollapsed)
}

var body: some View {

let addButton = ZStack(alignment: .top) {
Expand All @@ -49,7 +52,7 @@ struct Favorites: View {

VStack(spacing: 4) {

ForEach(isExpanded ? model.rows.indices : model.rows.indices.prefix(HomePage.favoritesRowCountWhenCollapsed), id: \.self) { index in
ForEach(rowIndices, id: \.self) { index in

HStack(alignment: .top, spacing: 20) {
ForEach(model.rows[index], id: \.id) { favorite in
Expand All @@ -69,7 +72,7 @@ struct Favorites: View {

}

MoreOrLess(isExpanded: $isExpanded)
MoreOrLess(isExpanded: $model.showAllFavorites)
.padding(.top, 2)
.visibility(model.rows.count > HomePage.favoritesRowCountWhenCollapsed && isHovering ? .visible : .invisible)

Expand Down Expand Up @@ -129,20 +132,28 @@ struct Favorite: View {

let bookmark: Bookmark

@State var isHovering = false

var body: some View {

FavoriteTemplate(title: bookmark.title, domain: bookmark.url.host)
.link {
model.open(bookmark)
}.contextMenu(ContextMenu(menuItems: {
Button(UserText.openInNewTab, action: { model.openInNewTab(bookmark) })
Button(UserText.openInNewWindow, action: { model.openInNewWindow(bookmark) })
Divider()
Button(UserText.edit, action: { model.edit(bookmark) })
Button(UserText.remove, action: { model.remove(bookmark) })
}))
.link(onHoverChanged: { isHovering in

if isHovering {
DispatchQueue.main.async {
NSCursor.pointingHand.push()
}
} else {
NSCursor.pointingHand.pop()
}

}) {
model.open(bookmark)
}.contextMenu(ContextMenu(menuItems: {
Button(UserText.openInNewTab, action: { model.openInNewTab(bookmark) })
Button(UserText.openInNewWindow, action: { model.openInNewWindow(bookmark) })
Divider()
Button(UserText.edit, action: { model.edit(bookmark) })
Button(UserText.remove, action: { model.remove(bookmark) })
}))

}

Expand Down
9 changes: 9 additions & 0 deletions DuckDuckGo/Home Page/View/HyperLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,17 @@ struct HyperLink: View {
var body: some View {
Text(text)
.foregroundColor(isHovering ? Color("LinkBlueColor") : textColor)
.optionalUnderline(isHovering)
.link {
isHovering = $0

if isHovering {
DispatchQueue.main.async {
NSCursor.pointingHand.push()
}
} else {
NSCursor.pointingHand.pop()
}
} clicked: {
action()
}
Expand Down
Loading