Remove private-note and notification from user (IOS-192)
This commit is contained in:
parent
7ab194b15d
commit
0b959f5bca
|
@ -7,7 +7,6 @@
|
|||
|
||||
import UIKit
|
||||
import CoreDataStack
|
||||
import class CoreDataStack.Notification
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
import MastodonLocalization
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import UIKit
|
||||
import CoreDataStack
|
||||
import MastodonSDK
|
||||
import class CoreDataStack.Notification
|
||||
|
||||
enum DataSourceItem: Hashable {
|
||||
case status(record: MastodonStatus)
|
||||
|
|
|
@ -15,7 +15,6 @@ import Meta
|
|||
import MastodonAsset
|
||||
import MastodonCore
|
||||
import MastodonLocalization
|
||||
import class CoreDataStack.Notification
|
||||
import MastodonSDK
|
||||
|
||||
extension NotificationView {
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
<attribute name="isLoadingMore" transient="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="kindRaw" attributeType="String"/>
|
||||
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="notification" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Notification" inverseName="feeds" inverseEntity="Notification"/>
|
||||
<relationship name="status" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="feeds" inverseEntity="Status"/>
|
||||
</entity>
|
||||
<entity name="Instance" representedClassName="CoreDataStack.Instance" syncable="YES">
|
||||
|
@ -119,10 +118,7 @@
|
|||
<relationship name="muted" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="mutedBy" inverseEntity="Status"/>
|
||||
<relationship name="muting" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="mutingBy" inverseEntity="MastodonUser"/>
|
||||
<relationship name="mutingBy" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="muting" inverseEntity="MastodonUser"/>
|
||||
<relationship name="notifications" toMany="YES" deletionRule="Nullify" destinationEntity="Notification" inverseName="account" inverseEntity="Notification"/>
|
||||
<relationship name="pinnedStatus" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="pinnedBy" inverseEntity="Status"/>
|
||||
<relationship name="privateNotes" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PrivateNote" inverseName="to" inverseEntity="PrivateNote"/>
|
||||
<relationship name="privateNotesTo" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PrivateNote" inverseName="from" inverseEntity="PrivateNote"/>
|
||||
<relationship name="reblogged" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="rebloggedBy" inverseEntity="Status"/>
|
||||
<relationship name="showingReblogs" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="showingReblogsBy" inverseEntity="MastodonUser"/>
|
||||
<relationship name="showingReblogsBy" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="showingReblogs" inverseEntity="MastodonUser"/>
|
||||
|
@ -130,19 +126,6 @@
|
|||
<relationship name="votePollOptions" toMany="YES" deletionRule="Nullify" destinationEntity="PollOption" inverseName="votedBy" inverseEntity="PollOption"/>
|
||||
<relationship name="votePolls" toMany="YES" deletionRule="Nullify" destinationEntity="Poll" inverseName="votedBy" inverseEntity="Poll"/>
|
||||
</entity>
|
||||
<entity name="Notification" representedClassName="CoreDataStack.Notification" syncable="YES">
|
||||
<attribute name="createAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="domain" attributeType="String"/>
|
||||
<attribute name="followRequestState" optional="YES" attributeType="Binary"/>
|
||||
<attribute name="id" attributeType="String"/>
|
||||
<attribute name="transientFollowRequestState" optional="YES" transient="YES" attributeType="Binary"/>
|
||||
<attribute name="typeRaw" attributeType="String"/>
|
||||
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="userID" attributeType="String"/>
|
||||
<relationship name="account" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="notifications" inverseEntity="MastodonUser"/>
|
||||
<relationship name="feeds" toMany="YES" deletionRule="Cascade" destinationEntity="Feed" inverseName="notification" inverseEntity="Feed"/>
|
||||
<relationship name="status" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="notifications" inverseEntity="Status"/>
|
||||
</entity>
|
||||
<entity name="Poll" representedClassName="CoreDataStack.Poll" syncable="YES">
|
||||
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="domain" attributeType="String" defaultValueString=""/>
|
||||
|
@ -168,12 +151,6 @@
|
|||
<relationship name="poll" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Poll" inverseName="options" inverseEntity="Poll"/>
|
||||
<relationship name="votedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="votePollOptions" inverseEntity="MastodonUser"/>
|
||||
</entity>
|
||||
<entity name="PrivateNote" representedClassName="CoreDataStack.PrivateNote" syncable="YES">
|
||||
<attribute name="note" optional="YES" attributeType="String"/>
|
||||
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="from" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="privateNotesTo" inverseEntity="MastodonUser"/>
|
||||
<relationship name="to" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="privateNotes" inverseEntity="MastodonUser"/>
|
||||
</entity>
|
||||
<entity name="Setting" representedClassName="CoreDataStack.Setting" syncable="YES">
|
||||
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="domain" attributeType="String"/>
|
||||
|
@ -216,7 +193,6 @@
|
|||
<relationship name="favouritedBy" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="favourite" inverseEntity="MastodonUser"/>
|
||||
<relationship name="feeds" toMany="YES" deletionRule="Cascade" destinationEntity="Feed" inverseName="status" inverseEntity="Feed"/>
|
||||
<relationship name="mutedBy" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="muted" inverseEntity="MastodonUser"/>
|
||||
<relationship name="notifications" toMany="YES" deletionRule="Cascade" destinationEntity="Notification" inverseName="status" inverseEntity="Notification"/>
|
||||
<relationship name="pinnedBy" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="pinnedStatus" inverseEntity="MastodonUser"/>
|
||||
<relationship name="poll" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Poll" inverseName="status" inverseEntity="Poll"/>
|
||||
<relationship name="reblog" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="reblogFrom" inverseEntity="Status"/>
|
||||
|
|
|
@ -96,19 +96,6 @@ extension Feed {
|
|||
public static func hasNotificationPredicate() -> NSPredicate {
|
||||
return NSPredicate(format: "%K != nil", #keyPath(Feed.notification))
|
||||
}
|
||||
|
||||
public static func notificationTypePredicate(types: [MastodonNotificationType]) -> NSPredicate {
|
||||
return NSCompoundPredicate(andPredicateWithSubpredicates: [
|
||||
hasNotificationPredicate(),
|
||||
NSPredicate(
|
||||
format: "%K.%K IN %@",
|
||||
#keyPath(Feed.notification),
|
||||
#keyPath(Notification.typeRaw),
|
||||
types.map { $0.rawValue }
|
||||
)
|
||||
])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - AutoGenerateProperty
|
||||
|
|
|
@ -66,7 +66,6 @@ final public class MastodonUser: NSManagedObject {
|
|||
|
||||
// one-to-many relationship
|
||||
@NSManaged public private(set) var statuses: Set<Status>
|
||||
@NSManaged public private(set) var notifications: Set<Notification>
|
||||
|
||||
// many-to-many relationship
|
||||
@NSManaged public private(set) var favourite: Set<Status>
|
||||
|
|
|
@ -1,269 +0,0 @@
|
|||
//
|
||||
// Notification.swift
|
||||
// CoreDataStack
|
||||
//
|
||||
// Created by sxiaojian on 2021/4/13.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
public final class Notification: NSManagedObject {
|
||||
public typealias ID = String
|
||||
|
||||
// sourcery: autoGenerateProperty
|
||||
@NSManaged public private(set) var id: ID
|
||||
// sourcery: autoGenerateProperty
|
||||
@NSManaged public private(set) var typeRaw: String
|
||||
// sourcery: autoGenerateProperty
|
||||
@NSManaged public private(set) var domain: String
|
||||
// sourcery: autoGenerateProperty
|
||||
@NSManaged public private(set) var userID: String
|
||||
|
||||
// sourcery: autoGenerateProperty
|
||||
@NSManaged public private(set) var createAt: Date
|
||||
// sourcery: autoUpdatableObject, autoGenerateProperty
|
||||
@NSManaged public private(set) var updatedAt: Date
|
||||
|
||||
// one-to-one relationship
|
||||
// sourcery: autoGenerateRelationship
|
||||
@NSManaged public private(set) var account: MastodonUser
|
||||
// sourcery: autoGenerateRelationship
|
||||
@NSManaged public private(set) var status: Status?
|
||||
|
||||
// many-to-one relationship
|
||||
@NSManaged public private(set) var feeds: Set<Feed>
|
||||
|
||||
}
|
||||
|
||||
extension Notification {
|
||||
// sourcery: autoUpdatableObject
|
||||
@objc public var followRequestState: MastodonFollowRequestState {
|
||||
get {
|
||||
let keyPath = #keyPath(Notification.followRequestState)
|
||||
willAccessValue(forKey: keyPath)
|
||||
let _data = primitiveValue(forKey: keyPath) as? Data
|
||||
didAccessValue(forKey: keyPath)
|
||||
do {
|
||||
guard let data = _data, !data.isEmpty else { return .init(state: .none) }
|
||||
let state = try JSONDecoder().decode(MastodonFollowRequestState.self, from: data)
|
||||
return state
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
return .init(state: .none)
|
||||
}
|
||||
}
|
||||
set {
|
||||
let keyPath = #keyPath(Notification.followRequestState)
|
||||
let data = try? JSONEncoder().encode(newValue)
|
||||
willChangeValue(forKey: keyPath)
|
||||
setPrimitiveValue(data, forKey: keyPath)
|
||||
didChangeValue(forKey: keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
// sourcery: autoUpdatableObject
|
||||
@objc public var transientFollowRequestState: MastodonFollowRequestState {
|
||||
get {
|
||||
let keyPath = #keyPath(Notification.transientFollowRequestState)
|
||||
willAccessValue(forKey: keyPath)
|
||||
let _data = primitiveValue(forKey: keyPath) as? Data
|
||||
didAccessValue(forKey: keyPath)
|
||||
do {
|
||||
guard let data = _data else { return .init(state: .none) }
|
||||
let state = try JSONDecoder().decode(MastodonFollowRequestState.self, from: data)
|
||||
return state
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
return .init(state: .none)
|
||||
}
|
||||
}
|
||||
set {
|
||||
let keyPath = #keyPath(Notification.transientFollowRequestState)
|
||||
let data = try? JSONEncoder().encode(newValue)
|
||||
willChangeValue(forKey: keyPath)
|
||||
setPrimitiveValue(data, forKey: keyPath)
|
||||
didChangeValue(forKey: keyPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Notification: FeedIndexable { }
|
||||
|
||||
extension Notification {
|
||||
@discardableResult
|
||||
public static func insert(
|
||||
into context: NSManagedObjectContext,
|
||||
property: Property,
|
||||
relationship: Relationship
|
||||
) -> Notification {
|
||||
let object: Notification = context.insertObject()
|
||||
|
||||
object.configure(property: property)
|
||||
object.configure(relationship: relationship)
|
||||
|
||||
return object
|
||||
}
|
||||
}
|
||||
|
||||
extension Notification: Managed {
|
||||
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||
return [NSSortDescriptor(keyPath: \Notification.createAt, ascending: false)]
|
||||
}
|
||||
}
|
||||
|
||||
extension Notification {
|
||||
static func predicate(domain: String) -> NSPredicate {
|
||||
return NSPredicate(format: "%K == %@", #keyPath(Notification.domain), domain)
|
||||
}
|
||||
|
||||
static func predicate(userID: String) -> NSPredicate {
|
||||
return NSPredicate(format: "%K == %@", #keyPath(Notification.userID), userID)
|
||||
}
|
||||
|
||||
static func predicate(id: ID) -> NSPredicate {
|
||||
return NSPredicate(format: "%K == %@", #keyPath(Notification.id), id)
|
||||
}
|
||||
|
||||
static func predicate(typeRaw: String) -> NSPredicate {
|
||||
return NSPredicate(format: "%K == %@", #keyPath(Notification.typeRaw), typeRaw)
|
||||
}
|
||||
|
||||
public static func predicate(
|
||||
domain: String,
|
||||
userID: String,
|
||||
id: ID
|
||||
) -> NSPredicate {
|
||||
return NSCompoundPredicate(andPredicateWithSubpredicates: [
|
||||
Notification.predicate(domain: domain),
|
||||
Notification.predicate(userID: userID),
|
||||
Notification.predicate(id: id)
|
||||
])
|
||||
}
|
||||
|
||||
public static func predicate(
|
||||
domain: String,
|
||||
userID: String,
|
||||
typeRaw: String? = nil
|
||||
) -> NSPredicate {
|
||||
if let typeRaw = typeRaw {
|
||||
return NSCompoundPredicate(andPredicateWithSubpredicates: [
|
||||
Notification.predicate(domain: domain),
|
||||
Notification.predicate(typeRaw: typeRaw),
|
||||
Notification.predicate(userID: userID),
|
||||
])
|
||||
} else {
|
||||
return NSCompoundPredicate(andPredicateWithSubpredicates: [
|
||||
Notification.predicate(domain: domain),
|
||||
Notification.predicate(userID: userID)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
public static func predicate(validTypesRaws types: [String]) -> NSPredicate {
|
||||
return NSPredicate(format: "%K IN %@", #keyPath(Notification.typeRaw), types)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - AutoGenerateProperty
|
||||
extension Notification: AutoGenerateProperty {
|
||||
// sourcery:inline:Notification.AutoGenerateProperty
|
||||
|
||||
// Generated using Sourcery
|
||||
// DO NOT EDIT
|
||||
public struct Property {
|
||||
public let id: ID
|
||||
public let typeRaw: String
|
||||
public let domain: String
|
||||
public let userID: String
|
||||
public let createAt: Date
|
||||
public let updatedAt: Date
|
||||
|
||||
public init(
|
||||
id: ID,
|
||||
typeRaw: String,
|
||||
domain: String,
|
||||
userID: String,
|
||||
createAt: Date,
|
||||
updatedAt: Date
|
||||
) {
|
||||
self.id = id
|
||||
self.typeRaw = typeRaw
|
||||
self.domain = domain
|
||||
self.userID = userID
|
||||
self.createAt = createAt
|
||||
self.updatedAt = updatedAt
|
||||
}
|
||||
}
|
||||
|
||||
public func configure(property: Property) {
|
||||
self.id = property.id
|
||||
self.typeRaw = property.typeRaw
|
||||
self.domain = property.domain
|
||||
self.userID = property.userID
|
||||
self.createAt = property.createAt
|
||||
self.updatedAt = property.updatedAt
|
||||
}
|
||||
|
||||
public func update(property: Property) {
|
||||
update(updatedAt: property.updatedAt)
|
||||
}
|
||||
// sourcery:end
|
||||
}
|
||||
|
||||
// MARK: - AutoGenerateRelationship
|
||||
extension Notification: AutoGenerateRelationship {
|
||||
// sourcery:inline:Notification.AutoGenerateRelationship
|
||||
|
||||
// Generated using Sourcery
|
||||
// DO NOT EDIT
|
||||
public struct Relationship {
|
||||
public let account: MastodonUser
|
||||
public let status: Status?
|
||||
|
||||
public init(
|
||||
account: MastodonUser,
|
||||
status: Status?
|
||||
) {
|
||||
self.account = account
|
||||
self.status = status
|
||||
}
|
||||
}
|
||||
|
||||
public func configure(relationship: Relationship) {
|
||||
self.account = relationship.account
|
||||
self.status = relationship.status
|
||||
}
|
||||
// sourcery:end
|
||||
}
|
||||
|
||||
// MARK: - AutoUpdatableObject
|
||||
extension Notification: AutoUpdatableObject {
|
||||
// sourcery:inline:Notification.AutoUpdatableObject
|
||||
|
||||
// Generated using Sourcery
|
||||
// DO NOT EDIT
|
||||
public func update(updatedAt: Date) {
|
||||
if self.updatedAt != updatedAt {
|
||||
self.updatedAt = updatedAt
|
||||
}
|
||||
}
|
||||
public func update(followRequestState: MastodonFollowRequestState) {
|
||||
if self.followRequestState != followRequestState {
|
||||
self.followRequestState = followRequestState
|
||||
}
|
||||
}
|
||||
public func update(transientFollowRequestState: MastodonFollowRequestState) {
|
||||
if self.transientFollowRequestState != transientFollowRequestState {
|
||||
self.transientFollowRequestState = transientFollowRequestState
|
||||
}
|
||||
}
|
||||
// sourcery:end
|
||||
}
|
||||
|
||||
extension Notification {
|
||||
public func attach(feed: Feed) {
|
||||
mutableSetValue(forKey: #keyPath(Notification.feeds)).add(feed)
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// PrivateNote.swift
|
||||
// CoreDataStack
|
||||
//
|
||||
// Created by MainasuK Cirno on 2021-4-1.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import Foundation
|
||||
|
||||
final public class PrivateNote: NSManagedObject {
|
||||
|
||||
@NSManaged public private(set) var note: String?
|
||||
|
||||
@NSManaged public private(set) var updatedAt: Date
|
||||
|
||||
// many-to-one relationship
|
||||
@NSManaged public private(set) var to: MastodonUser?
|
||||
@NSManaged public private(set) var from: MastodonUser
|
||||
|
||||
}
|
||||
|
||||
extension PrivateNote {
|
||||
public override func awakeFromInsert() {
|
||||
super.awakeFromInsert()
|
||||
setPrimitiveValue(Date(), forKey: #keyPath(PrivateNote.updatedAt))
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public static func insert(
|
||||
into context: NSManagedObjectContext,
|
||||
property: Property
|
||||
) -> PrivateNote {
|
||||
let privateNode: PrivateNote = context.insertObject()
|
||||
privateNode.note = property.note
|
||||
return privateNode
|
||||
}
|
||||
}
|
||||
|
||||
extension PrivateNote {
|
||||
public struct Property {
|
||||
public let note: String?
|
||||
|
||||
init(note: String) {
|
||||
self.note = note
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension PrivateNote: Managed {
|
||||
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||
return [NSSortDescriptor(keyPath: \PrivateNote.updatedAt, ascending: false)]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// Notification+Property.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by MainasuK on 2022-1-21.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreDataStack
|
||||
import MastodonSDK
|
||||
import class CoreDataStack.Notification
|
||||
|
||||
extension Notification.Property {
|
||||
public init(
|
||||
entity: Mastodon.Entity.Notification,
|
||||
domain: String,
|
||||
userID: String,
|
||||
networkDate: Date
|
||||
) {
|
||||
self.init(
|
||||
id: entity.id,
|
||||
typeRaw: entity.type.rawValue,
|
||||
domain: domain,
|
||||
userID: userID,
|
||||
createAt: entity.createdAt,
|
||||
updatedAt: networkDate
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
//
|
||||
// Persistence+Notification.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by MainasuK on 2022-1-21.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import CoreDataStack
|
||||
import Foundation
|
||||
import MastodonSDK
|
||||
import class CoreDataStack.Notification
|
||||
|
||||
extension Persistence.Notification {
|
||||
|
||||
public struct PersistContext {
|
||||
public let domain: String
|
||||
public let entity: Mastodon.Entity.Notification
|
||||
public let me: MastodonUser
|
||||
public let networkDate: Date
|
||||
|
||||
public init(
|
||||
domain: String,
|
||||
entity: Mastodon.Entity.Notification,
|
||||
me: MastodonUser,
|
||||
networkDate: Date
|
||||
) {
|
||||
self.domain = domain
|
||||
self.entity = entity
|
||||
self.me = me
|
||||
self.networkDate = networkDate
|
||||
}
|
||||
}
|
||||
|
||||
public struct PersistResult {
|
||||
public let notification: Notification
|
||||
public let isNewInsertion: Bool
|
||||
|
||||
public init(
|
||||
notification: Notification,
|
||||
isNewInsertion: Bool
|
||||
) {
|
||||
self.notification = notification
|
||||
self.isNewInsertion = isNewInsertion
|
||||
}
|
||||
}
|
||||
|
||||
public static func createOrMerge(
|
||||
in managedObjectContext: NSManagedObjectContext,
|
||||
context: PersistContext
|
||||
) -> PersistResult {
|
||||
|
||||
if let old = fetch(in: managedObjectContext, context: context) {
|
||||
merge(object: old, context: context)
|
||||
return PersistResult(
|
||||
notification: old,
|
||||
isNewInsertion: false
|
||||
)
|
||||
} else {
|
||||
let accountResult = Persistence.MastodonUser.createOrMerge(
|
||||
in: managedObjectContext,
|
||||
context: Persistence.MastodonUser.PersistContext(
|
||||
domain: context.domain,
|
||||
entity: context.entity.account,
|
||||
cache: nil,
|
||||
networkDate: context.networkDate
|
||||
)
|
||||
)
|
||||
let account = accountResult.user
|
||||
|
||||
let status: Status? = {
|
||||
guard let entity = context.entity.status else { return nil }
|
||||
let result = Persistence.Status.createOrMerge(
|
||||
in: managedObjectContext,
|
||||
context: Persistence.Status.PersistContext(
|
||||
domain: context.domain,
|
||||
entity: entity,
|
||||
me: context.me,
|
||||
statusCache: nil,
|
||||
userCache: nil,
|
||||
networkDate: context.networkDate
|
||||
)
|
||||
)
|
||||
return result.status
|
||||
}()
|
||||
|
||||
let relationship = Notification.Relationship(
|
||||
account: account,
|
||||
status: status
|
||||
)
|
||||
|
||||
let object = create(
|
||||
in: managedObjectContext,
|
||||
context: context,
|
||||
relationship: relationship
|
||||
)
|
||||
|
||||
return PersistResult(
|
||||
notification: object,
|
||||
isNewInsertion: true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Persistence.Notification {
|
||||
|
||||
public static func fetch(
|
||||
in managedObjectContext: NSManagedObjectContext,
|
||||
context: PersistContext
|
||||
) -> Notification? {
|
||||
let request = Notification.sortedFetchRequest
|
||||
request.predicate = Notification.predicate(
|
||||
domain: context.me.domain,
|
||||
userID: context.me.id,
|
||||
id: context.entity.id
|
||||
)
|
||||
request.fetchLimit = 1
|
||||
do {
|
||||
return try managedObjectContext.fetch(request).first
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public static func create(
|
||||
in managedObjectContext: NSManagedObjectContext,
|
||||
context: PersistContext,
|
||||
relationship: Notification.Relationship
|
||||
) -> Notification {
|
||||
let property = Notification.Property(
|
||||
entity: context.entity,
|
||||
domain: context.me.domain,
|
||||
userID: context.me.id,
|
||||
networkDate: context.networkDate
|
||||
)
|
||||
let object = Notification.insert(
|
||||
into: managedObjectContext,
|
||||
property: property,
|
||||
relationship: relationship
|
||||
)
|
||||
update(object: object, context: context)
|
||||
return object
|
||||
}
|
||||
|
||||
public static func merge(
|
||||
object: Notification,
|
||||
context: PersistContext
|
||||
) {
|
||||
guard context.networkDate > object.updatedAt else { return }
|
||||
let property = Notification.Property(
|
||||
entity: context.entity,
|
||||
domain: context.me.domain,
|
||||
userID: context.me.id,
|
||||
networkDate: context.networkDate
|
||||
)
|
||||
object.update(property: property)
|
||||
|
||||
if let status = object.status, let entity = context.entity.status {
|
||||
let property = Status.Property(
|
||||
entity: entity,
|
||||
domain: context.domain,
|
||||
networkDate: context.networkDate
|
||||
)
|
||||
status.update(property: property)
|
||||
}
|
||||
|
||||
let accountProperty = MastodonUser.Property(
|
||||
entity: context.entity.account,
|
||||
domain: context.domain,
|
||||
networkDate: context.networkDate
|
||||
)
|
||||
object.account.update(property: accountProperty)
|
||||
|
||||
if let author = object.status, let entity = context.entity.status {
|
||||
let property = Status.Property(
|
||||
entity: entity,
|
||||
domain: context.domain,
|
||||
networkDate: context.networkDate
|
||||
)
|
||||
author.update(property: property)
|
||||
}
|
||||
|
||||
update(object: object, context: context)
|
||||
}
|
||||
|
||||
private static func update(
|
||||
object: Notification,
|
||||
context: PersistContext
|
||||
) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
|
@ -68,21 +68,3 @@ extension APIService {
|
|||
return response
|
||||
}
|
||||
}
|
||||
|
||||
extension MastodonUser {
|
||||
func deleteStatusAndNotificationFeeds(in context: NSManagedObjectContext) {
|
||||
statuses.map {
|
||||
$0.feeds
|
||||
.union($0.reblogFrom.map { $0.feeds }.flatMap { $0 })
|
||||
.union($0.notifications.map { $0.feeds }.flatMap { $0 })
|
||||
}
|
||||
.flatMap { $0 }
|
||||
.forEach(context.delete)
|
||||
|
||||
notifications.map {
|
||||
$0.feeds
|
||||
}
|
||||
.flatMap { $0 }
|
||||
.forEach(context.delete)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,21 +40,6 @@ extension APIService {
|
|||
authorization: authenticationBox.userAuthorization
|
||||
).singleOutput()
|
||||
|
||||
let userIDs = response.value.map { $0.id }
|
||||
let predicate = MastodonUser.predicate(domain: authenticationBox.domain, ids: userIDs)
|
||||
|
||||
let fetchRequest = MastodonUser.fetchRequest()
|
||||
fetchRequest.predicate = predicate
|
||||
fetchRequest.includesPropertyValues = false
|
||||
|
||||
try await managedObjectContext.performChanges {
|
||||
let users = try managedObjectContext.fetch(fetchRequest) as! [MastodonUser]
|
||||
|
||||
for user in users {
|
||||
user.deleteStatusAndNotificationFeeds(in: managedObjectContext)
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ import CoreDataStack
|
|||
import Foundation
|
||||
import MastodonSDK
|
||||
import OSLog
|
||||
import class CoreDataStack.Notification
|
||||
|
||||
extension APIService {
|
||||
|
||||
|
@ -86,74 +85,6 @@ extension APIService {
|
|||
authorization: authorization
|
||||
).singleOutput()
|
||||
|
||||
let managedObjectContext = self.backgroundManagedObjectContext
|
||||
try await managedObjectContext.performChanges {
|
||||
guard let me = authenticationBox.authentication.user(in: managedObjectContext) else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
var notifications: [Notification] = []
|
||||
for entity in response.value {
|
||||
let result = Persistence.Notification.createOrMerge(
|
||||
in: managedObjectContext,
|
||||
context: Persistence.Notification.PersistContext(
|
||||
domain: authenticationBox.domain,
|
||||
entity: entity,
|
||||
me: me,
|
||||
networkDate: response.networkDate
|
||||
)
|
||||
)
|
||||
notifications.append(result.notification)
|
||||
}
|
||||
|
||||
// locate anchor notification
|
||||
let anchorNotification: Notification? = {
|
||||
guard let maxID = query.maxID else { return nil }
|
||||
let request = Notification.sortedFetchRequest
|
||||
request.predicate = Notification.predicate(
|
||||
domain: authenticationBox.domain,
|
||||
userID: authenticationBox.userID,
|
||||
id: maxID
|
||||
)
|
||||
request.fetchLimit = 1
|
||||
return try? managedObjectContext.fetch(request).first
|
||||
}()
|
||||
|
||||
// update hasMore flag for anchor status
|
||||
let acct = Feed.Acct.mastodon(domain: authenticationBox.domain, userID: authenticationBox.userID)
|
||||
let kind: Feed.Kind = scope == .everything ? .notificationAll : .notificationMentions
|
||||
if let anchorNotification = anchorNotification,
|
||||
let feed = anchorNotification.feed(kind: kind, acct: acct) {
|
||||
feed.update(hasMore: false)
|
||||
}
|
||||
|
||||
// persist Feed relationship
|
||||
let sortedNotifications = notifications.sorted(by: { $0.createAt < $1.createAt })
|
||||
let oldestNotification = sortedNotifications.first
|
||||
for notification in notifications {
|
||||
let _feed = notification.feed(kind: kind, acct: acct)
|
||||
if let feed = _feed {
|
||||
feed.update(updatedAt: response.networkDate)
|
||||
} else {
|
||||
let feedProperty = Feed.Property(
|
||||
acct: acct,
|
||||
kind: kind,
|
||||
hasMore: false,
|
||||
createdAt: notification.createAt,
|
||||
updatedAt: response.networkDate
|
||||
)
|
||||
let feed = Feed.insert(into: managedObjectContext, property: feedProperty)
|
||||
notification.attach(feed: feed)
|
||||
|
||||
// set hasMore on oldest notification if is new feed
|
||||
if notification === oldestNotification {
|
||||
feed.update(hasMore: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
}
|
||||
|
@ -174,20 +105,6 @@ extension APIService {
|
|||
authorization: authorization
|
||||
).singleOutput()
|
||||
|
||||
let managedObjectContext = self.backgroundManagedObjectContext
|
||||
try await managedObjectContext.performChanges {
|
||||
guard let me = authenticationBox.authentication.user(in: managedObjectContext) else { return }
|
||||
_ = Persistence.Notification.createOrMerge(
|
||||
in: managedObjectContext,
|
||||
context: Persistence.Notification.PersistContext(
|
||||
domain: domain,
|
||||
entity: response.value,
|
||||
me: me,
|
||||
networkDate: response.networkDate
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue