Skip to content

Commit

Permalink
Merge branch 'main' into sam/update-wireguard-framework-to-1.1.3
Browse files Browse the repository at this point in the history
* main:
  Improves VPN pixel info and adds tests (#732)
  Reset Cache on Subscription Purchase & Restore (#719)
  Revert "Remove Autoconsent subfeature (#697)" (#730)
  Stub objects for Bookmarks sync (#713)
  • Loading branch information
samsymons committed Mar 18, 2024
2 parents 979cdaf + eced8f9 commit adc57eb
Show file tree
Hide file tree
Showing 30 changed files with 545 additions and 62 deletions.
3 changes: 3 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,9 @@ let package = Package(
.copy("Resources/Bookmarks_V4.sqlite"),
.copy("Resources/Bookmarks_V4.sqlite-shm"),
.copy("Resources/Bookmarks_V4.sqlite-wal"),
.copy("Resources/Bookmarks_V5.sqlite"),
.copy("Resources/Bookmarks_V5.sqlite-shm"),
.copy("Resources/Bookmarks_V5.sqlite-wal"),
],
plugins: [swiftlintPlugin]
),
Expand Down
15 changes: 13 additions & 2 deletions Sources/Bookmarks/BookmarkEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class BookmarkEntity: NSManagedObject {
@NSManaged public var title: String?
@NSManaged public var url: String?
@NSManaged public var uuid: String?
@NSManaged public var isStub: Bool
@NSManaged public var children: NSOrderedSet?
@NSManaged public fileprivate(set) var lastChildrenPayloadReceivedFromSync: String?
@NSManaged public fileprivate(set) var favoriteFolders: NSSet?
Expand Down Expand Up @@ -127,6 +128,16 @@ public class BookmarkEntity: NSManagedObject {
try validate()
}

public override func prepareForDeletion() {
super.prepareForDeletion()

if isFolder {
for child in children?.array as? [BookmarkEntity] ?? [] where child.isStub {
managedObjectContext?.delete(child)
}
}
}

public var urlObject: URL? {
guard let url = url else { return nil }
return url.isBookmarklet() ? url.toEncodedBookmarklet() : URL(string: url)
Expand All @@ -138,12 +149,12 @@ public class BookmarkEntity: NSManagedObject {

public var childrenArray: [BookmarkEntity] {
let children = children?.array as? [BookmarkEntity] ?? []
return children.filter { $0.isPendingDeletion == false }
return children.filter { $0.isStub == false && $0.isPendingDeletion == false }
}

public var favoritesArray: [BookmarkEntity] {
let children = favorites?.array as? [BookmarkEntity] ?? []
return children.filter { $0.isPendingDeletion == false }
return children.filter { $0.isStub == false && $0.isPendingDeletion == false }
}

public var favoriteFoldersSet: Set<BookmarkEntity> {
Expand Down
5 changes: 3 additions & 2 deletions Sources/Bookmarks/BookmarkListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,10 @@ public class BookmarkListViewModel: BookmarkListInteracting, ObservableObject {
public var totalBookmarksCount: Int {
let countRequest = BookmarkEntity.fetchRequest()
countRequest.predicate = NSPredicate(
format: "%K == false && %K == NO",
format: "%K == false && %K == NO && (%K == NO OR %K == nil)",
#keyPath(BookmarkEntity.isFolder),
#keyPath(BookmarkEntity.isPendingDeletion)
#keyPath(BookmarkEntity.isPendingDeletion),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub)
)

return (try? context.count(for: countRequest)) ?? 0
Expand Down
32 changes: 25 additions & 7 deletions Sources/Bookmarks/BookmarkUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ public struct BookmarkUtils {
public static func fetchOrphanedEntities(_ context: NSManagedObjectContext) -> [BookmarkEntity] {
let request = BookmarkEntity.fetchRequest()
request.predicate = NSPredicate(
format: "NOT %K IN %@ AND %K == NO AND %K == nil",
format: "NOT %K IN %@ AND %K == NO AND (%K == NO OR %K == nil) AND %K == nil",
#keyPath(BookmarkEntity.uuid),
BookmarkEntity.Constants.favoriteFoldersIDs.union([BookmarkEntity.Constants.rootFolderID]),
#keyPath(BookmarkEntity.isPendingDeletion),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub),
#keyPath(BookmarkEntity.parent)
)
request.sortDescriptors = [NSSortDescriptor(key: #keyPath(BookmarkEntity.uuid), ascending: true)]
Expand All @@ -71,6 +72,17 @@ public struct BookmarkUtils {
return (try? context.fetch(request)) ?? []
}

public static func fetchStubbedEntities(_ context: NSManagedObjectContext) -> [BookmarkEntity] {
let request = BookmarkEntity.fetchRequest()
request.predicate = NSPredicate(format: "%K == YES",
#keyPath(BookmarkEntity.isStub)
)
request.sortDescriptors = [NSSortDescriptor(key: #keyPath(BookmarkEntity.uuid), ascending: true)]
request.returnsObjectsAsFaults = false

return (try? context.fetch(request)) ?? []
}

public static func prepareFoldersStructure(in context: NSManagedObjectContext) {

if fetchRootFolder(context) == nil {
Expand Down Expand Up @@ -117,9 +129,10 @@ public struct BookmarkUtils {

public static func fetchAllBookmarksUUIDs(in context: NSManagedObjectContext) -> [String] {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "BookmarkEntity")
request.predicate = NSPredicate(format: "%K == NO AND %K == NO",
request.predicate = NSPredicate(format: "%K == NO AND %K == NO AND (%K == NO OR %K == nil)",
#keyPath(BookmarkEntity.isFolder),
#keyPath(BookmarkEntity.isPendingDeletion))
#keyPath(BookmarkEntity.isPendingDeletion),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub))
request.resultType = .dictionaryResultType
request.propertiesToFetch = [#keyPath(BookmarkEntity.uuid)]

Expand All @@ -131,10 +144,11 @@ public struct BookmarkUtils {
predicate: NSPredicate = NSPredicate(value: true),
context: NSManagedObjectContext) -> BookmarkEntity? {
let request = BookmarkEntity.fetchRequest()
let urlPredicate = NSPredicate(format: "%K == %@ AND %K == NO",
let urlPredicate = NSPredicate(format: "%K == %@ AND %K == NO AND (%K == NO OR %K == nil)",
#keyPath(BookmarkEntity.url),
url.absoluteString,
#keyPath(BookmarkEntity.isPendingDeletion))
#keyPath(BookmarkEntity.isPendingDeletion),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub))
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [urlPredicate, predicate])
request.returnsObjectsAsFaults = false
request.fetchLimit = 1
Expand All @@ -144,14 +158,18 @@ public struct BookmarkUtils {

public static func fetchBookmarksPendingDeletion(_ context: NSManagedObjectContext) -> [BookmarkEntity] {
let request = BookmarkEntity.fetchRequest()
request.predicate = NSPredicate(format: "%K == YES", #keyPath(BookmarkEntity.isPendingDeletion))
request.predicate = NSPredicate(format: "%K == YES AND (%K == NO OR %K == nil)",
#keyPath(BookmarkEntity.isPendingDeletion),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub))

return (try? context.fetch(request)) ?? []
}

public static func fetchModifiedBookmarks(_ context: NSManagedObjectContext) -> [BookmarkEntity] {
let request = BookmarkEntity.fetchRequest()
request.predicate = NSPredicate(format: "%K != nil", #keyPath(BookmarkEntity.modifiedAt))
request.predicate = NSPredicate(format: "%K != nil AND (%K == NO OR %K == nil)",
#keyPath(BookmarkEntity.modifiedAt),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub))

return (try? context.fetch(request)) ?? []
}
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>BookmarksModel 5.xcdatamodel</string>
<string>BookmarksModel 6.xcdatamodel</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22522" systemVersion="22G313" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="BookmarkEntity" representedClassName="BookmarkEntity" syncable="YES">
<attribute name="isFolder" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="isPendingDeletion" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" versionHashModifier="3"/>
<attribute name="isStub" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="lastChildrenPayloadReceivedFromSync" optional="YES" attributeType="String"/>
<attribute name="modifiedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="title" optional="YES" attributeType="String"/>
<attribute name="url" optional="YES" attributeType="String" versionHashModifier="3"/>
<attribute name="uuid" attributeType="String" versionHashModifier="3"/>
<relationship name="children" optional="YES" toMany="YES" deletionRule="Cascade" ordered="YES" destinationEntity="BookmarkEntity" inverseName="parent" inverseEntity="BookmarkEntity"/>
<relationship name="favoriteFolders" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="BookmarkEntity" inverseName="favorites" inverseEntity="BookmarkEntity" elementID="favoriteFolder"/>
<relationship name="favorites" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="BookmarkEntity" inverseName="favoriteFolders" inverseEntity="BookmarkEntity"/>
<relationship name="parent" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="BookmarkEntity" inverseName="children" inverseEntity="BookmarkEntity"/>
<fetchIndex name="byUUID">
<fetchIndexElement property="uuid" type="Binary" order="ascending"/>
<fetchIndexElement property="isPendingDeletion" type="Binary" order="ascending"/>
</fetchIndex>
<fetchIndex name="byURL">
<fetchIndexElement property="url" type="Binary" order="ascending"/>
<fetchIndexElement property="isPendingDeletion" type="Binary" order="ascending"/>
</fetchIndex>
<fetchIndex name="byIsPendingDeletion">
<fetchIndexElement property="isPendingDeletion" type="Binary" order="ascending"/>
</fetchIndex>
</entity>
</model>
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,11 @@ final class FaviconsFetchOperation: Operation {
private func mapBookmarkDomainsToUUIDs(for uuids: any Sequence & CVarArg) -> BookmarkDomains {
let request = BookmarkEntity.fetchRequest()
request.predicate = NSPredicate(
format: "%K IN %@ AND %K == NO AND %K == NO",
format: "%K IN %@ AND %K == NO AND %K == NO AND (%K == NO OR %K == nil)",
#keyPath(BookmarkEntity.uuid), uuids,
#keyPath(BookmarkEntity.isFolder),
#keyPath(BookmarkEntity.isPendingDeletion)
#keyPath(BookmarkEntity.isPendingDeletion),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub)
)
request.propertiesToFetch = [#keyPath(BookmarkEntity.uuid), #keyPath(BookmarkEntity.url)]
request.relationshipKeyPathsForPrefetching = [#keyPath(BookmarkEntity.favoriteFolders), #keyPath(BookmarkEntity.parent)]
Expand Down
5 changes: 3 additions & 2 deletions Sources/Bookmarks/ImportExport/BookmarkCoreDataImporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ public class BookmarkCoreDataImporter {
private func bookmarkURLToID(in context: NSManagedObjectContext) throws -> [String: NSManagedObjectID] {
let fetch = NSFetchRequest<NSFetchRequestResult>(entityName: "BookmarkEntity")
fetch.predicate = NSPredicate(
format: "%K == false && %K == NO",
format: "%K == false && %K == NO AND (%K == NO OR %K == nil)",
#keyPath(BookmarkEntity.isFolder),
#keyPath(BookmarkEntity.isPendingDeletion)
#keyPath(BookmarkEntity.isPendingDeletion),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub)
)
fetch.resultType = .dictionaryResultType

Expand Down
5 changes: 3 additions & 2 deletions Sources/Bookmarks/MenuBookmarksViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,11 @@ public class MenuBookmarksViewModel: MenuBookmarksInteracting {
}
return BookmarkUtils.fetchBookmark(for: url,
predicate: NSPredicate(
format: "ANY %K CONTAINS %@ AND %K == NO",
format: "ANY %K CONTAINS %@ AND %K == NO AND (%K == NO OR %K == nil)",
#keyPath(BookmarkEntity.favoriteFolders),
favoritesFolder,
#keyPath(BookmarkEntity.isPendingDeletion)
#keyPath(BookmarkEntity.isPendingDeletion),
#keyPath(BookmarkEntity.isStub), #keyPath(BookmarkEntity.isStub)
),
context: context)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Bookmarks
struct BookmarksTestDBBuilder {

static func main() {
generateDatabase(modelVersion: 3)
generateDatabase(modelVersion: 5)
}

private static func generateDatabase(modelVersion: Int) {
Expand Down
Loading

0 comments on commit adc57eb

Please sign in to comment.