188 lines
5.4 KiB
Swift
188 lines
5.4 KiB
Swift
import CoreData
|
|
import Foundation
|
|
import Models
|
|
|
|
struct InternalLibraryItem {
|
|
let id: String
|
|
let title: String
|
|
let createdAt: Date
|
|
let savedAt: Date
|
|
let readAt: Date?
|
|
let updatedAt: Date
|
|
let folder: String
|
|
let state: ArticleContentStatus
|
|
var readingProgress: Double
|
|
var readingProgressAnchor: Int
|
|
let imageURLString: String?
|
|
let onDeviceImageURLString: String?
|
|
let documentDirectoryPath: String?
|
|
let pageURLString: String
|
|
let descriptionText: String?
|
|
let publisherURLString: String?
|
|
let siteName: String?
|
|
let author: String?
|
|
let publishDate: Date?
|
|
let slug: String
|
|
let isArchived: Bool
|
|
let contentReader: String?
|
|
let htmlContent: String?
|
|
let originalHtml: String?
|
|
let language: String?
|
|
let wordsCount: Int?
|
|
let downloadURL: String
|
|
let recommendations: [InternalRecommendation]
|
|
var labels: [InternalLinkedItemLabel]
|
|
var highlights: [InternalHighlight]
|
|
|
|
var isPDF: Bool {
|
|
if let contentReader = contentReader {
|
|
return contentReader == "PDF"
|
|
}
|
|
return pageURLString.hasSuffix("pdf")
|
|
}
|
|
|
|
func asManagedObject(inContext context: NSManagedObjectContext) -> LibraryItem {
|
|
let existingItem = LibraryItem.lookup(byID: id, inContext: context)
|
|
let linkedItem = existingItem ?? LibraryItem(entity: LibraryItem.entity(), insertInto: context)
|
|
|
|
linkedItem.id = id
|
|
linkedItem.title = title
|
|
linkedItem.createdAt = createdAt
|
|
linkedItem.savedAt = savedAt
|
|
linkedItem.updatedAt = updatedAt
|
|
linkedItem.readAt = readAt
|
|
linkedItem.folder = folder
|
|
linkedItem.state = state.rawValue
|
|
linkedItem.readingProgress = readingProgress
|
|
linkedItem.readingProgressAnchor = Int64(readingProgressAnchor)
|
|
linkedItem.imageURLString = imageURLString
|
|
linkedItem.onDeviceImageURLString = onDeviceImageURLString
|
|
linkedItem.pageURLString = pageURLString
|
|
linkedItem.descriptionText = descriptionText
|
|
linkedItem.publisherURLString = publisherURLString
|
|
linkedItem.siteName = siteName
|
|
linkedItem.author = author
|
|
linkedItem.publishDate = publishDate
|
|
linkedItem.readAt = readAt
|
|
linkedItem.slug = slug
|
|
linkedItem.isArchived = isArchived
|
|
linkedItem.contentReader = contentReader
|
|
linkedItem.htmlContent = htmlContent
|
|
linkedItem.originalHtml = originalHtml
|
|
linkedItem.language = language
|
|
linkedItem.wordsCount = Int64(wordsCount ?? 0)
|
|
linkedItem.downloadURL = downloadURL
|
|
|
|
// Remove existing labels in case a label had been deleted
|
|
if let existingLabels = linkedItem.labels {
|
|
linkedItem.removeFromLabels(existingLabels)
|
|
}
|
|
|
|
for label in labels {
|
|
linkedItem.addToLabels(label.asManagedObject(inContext: context))
|
|
}
|
|
|
|
if let existingRecommendation = linkedItem.recommendations {
|
|
linkedItem.removeFromRecommendations(existingRecommendation)
|
|
}
|
|
|
|
for recommendation in recommendations {
|
|
linkedItem.addToRecommendations(recommendation.asManagedObject(inContext: context))
|
|
}
|
|
|
|
// Remove existing labels in case a label had been deleted
|
|
if let existingHighlights = linkedItem.highlights {
|
|
linkedItem.removeFromHighlights(existingHighlights)
|
|
}
|
|
|
|
for highlight in highlights {
|
|
linkedItem.addToHighlights(highlight.asManagedObject(context: context))
|
|
}
|
|
|
|
return linkedItem
|
|
}
|
|
}
|
|
|
|
extension Sequence where Element == InternalLibraryItem {
|
|
func persist(context: NSManagedObjectContext) -> [NSManagedObjectID]? {
|
|
var linkedItems: [LibraryItem]?
|
|
context.performAndWait {
|
|
linkedItems = map { $0.asManagedObject(inContext: context) }
|
|
|
|
do {
|
|
try context.save()
|
|
print("LinkedItems saved succesfully")
|
|
} catch {
|
|
context.rollback()
|
|
print(error)
|
|
print("Failed to save LinkedItems: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
if let linkedItems = linkedItems {
|
|
return linkedItems.map(\.objectID)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
public extension DataService {
|
|
func persist(jsonArticle: JSONArticle) -> NSManagedObjectID? {
|
|
jsonArticle.persistAsLinkedItem(context: backgroundContext)
|
|
}
|
|
}
|
|
|
|
extension JSONArticle {
|
|
func persistAsLinkedItem(context: NSManagedObjectContext) -> NSManagedObjectID? {
|
|
var objectID: NSManagedObjectID?
|
|
|
|
let internalLinkedItem = InternalLibraryItem(
|
|
id: id,
|
|
title: title,
|
|
createdAt: createdAt,
|
|
savedAt: savedAt,
|
|
readAt: readAt,
|
|
updatedAt: updatedAt,
|
|
folder: folder,
|
|
state: .succeeded,
|
|
readingProgress: readingProgressPercent,
|
|
readingProgressAnchor: readingProgressAnchorIndex,
|
|
imageURLString: image,
|
|
onDeviceImageURLString: nil,
|
|
documentDirectoryPath: nil,
|
|
pageURLString: url,
|
|
descriptionText: title,
|
|
publisherURLString: nil,
|
|
siteName: nil,
|
|
author: nil,
|
|
publishDate: nil,
|
|
slug: slug,
|
|
isArchived: isArchived,
|
|
contentReader: contentReader,
|
|
htmlContent: nil,
|
|
originalHtml: nil,
|
|
language: language,
|
|
wordsCount: wordsCount,
|
|
downloadURL: downloadURL,
|
|
recommendations: [],
|
|
labels: [],
|
|
highlights: []
|
|
)
|
|
|
|
context.performAndWait {
|
|
objectID = internalLinkedItem.asManagedObject(inContext: context).objectID
|
|
|
|
do {
|
|
try context.save()
|
|
logger.debug("LinkedItem saved succesfully")
|
|
} catch {
|
|
context.rollback()
|
|
logger.debug("Failed to save LinkedItem: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
return objectID
|
|
}
|
|
}
|