update archive and delete link mutations to work off of core data
This commit is contained in:
@ -163,7 +163,7 @@ import Views
|
||||
withAnimation(.linear(duration: 0.4)) {
|
||||
viewModel.setLinkArchived(
|
||||
dataService: dataService,
|
||||
linkId: item.unwrappedID,
|
||||
objectID: item.objectID,
|
||||
archived: !item.isArchived
|
||||
)
|
||||
}
|
||||
@ -193,7 +193,7 @@ import Views
|
||||
if !item.isArchived {
|
||||
Button {
|
||||
withAnimation(.linear(duration: 0.4)) {
|
||||
viewModel.setLinkArchived(dataService: dataService, linkId: item.unwrappedID, archived: true)
|
||||
viewModel.setLinkArchived(dataService: dataService, objectID: item.objectID, archived: true)
|
||||
}
|
||||
} label: {
|
||||
Label("Archive", systemImage: "archivebox")
|
||||
@ -201,7 +201,7 @@ import Views
|
||||
} else {
|
||||
Button {
|
||||
withAnimation(.linear(duration: 0.4)) {
|
||||
viewModel.setLinkArchived(dataService: dataService, linkId: item.unwrappedID, archived: false)
|
||||
viewModel.setLinkArchived(dataService: dataService, objectID: item.objectID, archived: false)
|
||||
}
|
||||
} label: {
|
||||
Label("Unarchive", systemImage: "tray.and.arrow.down.fill")
|
||||
@ -223,7 +223,7 @@ import Views
|
||||
Button("Remove Link", role: .destructive) {
|
||||
if let itemToRemove = itemToRemove {
|
||||
withAnimation {
|
||||
viewModel.removeLink(dataService: dataService, linkId: itemToRemove.unwrappedID)
|
||||
viewModel.removeLink(dataService: dataService, objectID: itemToRemove.objectID)
|
||||
}
|
||||
}
|
||||
self.itemToRemove = nil
|
||||
@ -275,7 +275,7 @@ import Views
|
||||
func contextMenuActionHandler(item: LinkedItem, action: GridCardAction) {
|
||||
switch action {
|
||||
case .toggleArchiveStatus:
|
||||
viewModel.setLinkArchived(dataService: dataService, linkId: item.unwrappedID, archived: !item.isArchived)
|
||||
viewModel.setLinkArchived(dataService: dataService, objectID: item.objectID, archived: !item.isArchived)
|
||||
case .delete:
|
||||
itemToRemove = item
|
||||
confirmationShown = true
|
||||
@ -298,7 +298,7 @@ import Views
|
||||
Button("Remove Link", role: .destructive) {
|
||||
if let itemToRemove = itemToRemove {
|
||||
withAnimation {
|
||||
viewModel.removeLink(dataService: dataService, linkId: itemToRemove.unwrappedID)
|
||||
viewModel.removeLink(dataService: dataService, objectID: itemToRemove.objectID)
|
||||
}
|
||||
}
|
||||
self.itemToRemove = nil
|
||||
|
||||
@ -106,35 +106,19 @@ import Views
|
||||
.store(in: &subscriptions)
|
||||
}
|
||||
|
||||
func setLinkArchived(dataService: DataService, linkId: String, archived: Bool) {
|
||||
func setLinkArchived(dataService: DataService, objectID: NSManagedObjectID, archived: Bool) {
|
||||
// TODO: remove this by making list always fetch from Coredata
|
||||
if let itemIndex = items.firstIndex(where: { $0.id == linkId }) {
|
||||
items.remove(at: itemIndex)
|
||||
}
|
||||
dataService.archiveLink(itemID: linkId, archived: archived)
|
||||
guard let itemIndex = items.firstIndex(where: { $0.objectID == objectID }) else { return }
|
||||
items.remove(at: itemIndex)
|
||||
dataService.archiveLink(objectID: objectID, archived: archived)
|
||||
Snackbar.show(message: archived ? "Link archived" : "Link moved to Inbox")
|
||||
}
|
||||
|
||||
func removeLink(dataService: DataService, linkId: String) {
|
||||
isLoading = true
|
||||
|
||||
if let itemIndex = items.firstIndex(where: { $0.id == linkId }) {
|
||||
items.remove(at: itemIndex)
|
||||
}
|
||||
|
||||
dataService.removeLinkPublisher(itemID: linkId)
|
||||
.sink(
|
||||
receiveCompletion: { [weak self] completion in
|
||||
guard case .failure = completion else { return }
|
||||
self?.isLoading = false
|
||||
Snackbar.show(message: "Failed to remove link")
|
||||
},
|
||||
receiveValue: { [weak self] _ in
|
||||
self?.isLoading = false
|
||||
Snackbar.show(message: "Link removed")
|
||||
}
|
||||
)
|
||||
.store(in: &subscriptions)
|
||||
func removeLink(dataService: DataService, objectID: NSManagedObjectID) {
|
||||
guard let itemIndex = items.firstIndex(where: { $0.objectID == objectID }) else { return }
|
||||
items.remove(at: itemIndex)
|
||||
Snackbar.show(message: "Link removed")
|
||||
dataService.removeLink(objectID: objectID)
|
||||
}
|
||||
|
||||
func snoozeUntil(dataService: DataService, linkId: String, until: Date, successMessage: String?) {
|
||||
@ -164,13 +148,6 @@ import Views
|
||||
.store(in: &subscriptions)
|
||||
}
|
||||
|
||||
private func updateProgress(itemID: String, progress: Double) {
|
||||
guard let item = items.first(where: { $0.id == itemID }) else { return }
|
||||
if let index = items.firstIndex(of: item) {
|
||||
items[index].readingProgress = progress
|
||||
}
|
||||
}
|
||||
|
||||
private var searchQuery: String? {
|
||||
if searchTerm.isEmpty, selectedLabels.isEmpty {
|
||||
return nil
|
||||
|
||||
@ -22,11 +22,15 @@ enum PDFProvider {
|
||||
}
|
||||
|
||||
func handleArchiveAction(dataService: DataService) {
|
||||
homeFeedViewModel.setLinkArchived(dataService: dataService, linkId: item.unwrappedID, archived: !item.isArchived)
|
||||
homeFeedViewModel.setLinkArchived(
|
||||
dataService: dataService,
|
||||
objectID: item.objectID,
|
||||
archived: !item.isArchived
|
||||
)
|
||||
}
|
||||
|
||||
func handleDeleteAction(dataService: DataService) {
|
||||
homeFeedViewModel.removeLink(dataService: dataService, linkId: item.unwrappedID)
|
||||
homeFeedViewModel.removeLink(dataService: dataService, objectID: item.objectID)
|
||||
}
|
||||
|
||||
func updateItemReadStatus(dataService: DataService) {
|
||||
|
||||
@ -93,7 +93,7 @@ import WebKit
|
||||
action: {
|
||||
homeFeedViewModel.setLinkArchived(
|
||||
dataService: dataService,
|
||||
linkId: item.unwrappedID,
|
||||
objectID: item.objectID,
|
||||
archived: !item.isArchived
|
||||
)
|
||||
},
|
||||
@ -125,7 +125,7 @@ import WebKit
|
||||
}
|
||||
.alert("Are you sure?", isPresented: $showDeleteConfirmation) {
|
||||
Button("Remove Link", role: .destructive) {
|
||||
homeFeedViewModel.removeLink(dataService: dataService, linkId: item.unwrappedID)
|
||||
homeFeedViewModel.removeLink(dataService: dataService, objectID: item.objectID)
|
||||
}
|
||||
Button("Cancel", role: .cancel, action: {})
|
||||
}
|
||||
|
||||
@ -1,19 +1,22 @@
|
||||
import CoreData
|
||||
import Foundation
|
||||
import Models
|
||||
import SwiftGraphQL
|
||||
|
||||
extension DataService {
|
||||
public func archiveLink(itemID: String, archived: Bool) {
|
||||
public func archiveLink(objectID: NSManagedObjectID, archived: Bool) {
|
||||
// Update CoreData
|
||||
if let linkedItem = LinkedItem.lookup(byID: itemID, inContext: backgroundContext) {
|
||||
linkedItem.update(inContext: backgroundContext, newIsArchivedValue: archived)
|
||||
}
|
||||
backgroundContext.perform { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let linkedItem = self.backgroundContext.object(with: objectID) as? LinkedItem else { return }
|
||||
linkedItem.update(inContext: self.backgroundContext, newIsArchivedValue: archived)
|
||||
|
||||
// Send update to server
|
||||
syncLinkArchiveStatus(itemID: itemID, archived: archived)
|
||||
// Send update to server
|
||||
self.syncLinkArchiveStatus(itemID: linkedItem.unwrappedID, objectID: objectID, archived: archived)
|
||||
}
|
||||
}
|
||||
|
||||
func syncLinkArchiveStatus(itemID: String, archived: Bool) {
|
||||
func syncLinkArchiveStatus(itemID: String, objectID: NSManagedObjectID, archived: Bool) {
|
||||
enum MutationResult {
|
||||
case success(linkId: String)
|
||||
case error(errorCode: Enums.ArchiveLinkErrorCode)
|
||||
@ -45,7 +48,7 @@ extension DataService {
|
||||
let syncStatus: ServerSyncStatus = data == nil ? .needsUpdate : .isNSync
|
||||
|
||||
context.perform {
|
||||
guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: context) else { return }
|
||||
guard let linkedItem = context.object(with: objectID) as? LinkedItem else { return }
|
||||
linkedItem.serverSyncStatus = Int64(syncStatus.rawValue)
|
||||
|
||||
do {
|
||||
|
||||
@ -1,16 +1,23 @@
|
||||
import Combine
|
||||
import CoreData
|
||||
import Foundation
|
||||
import Models
|
||||
import SwiftGraphQL
|
||||
|
||||
let setBookmarkedArticleSelection = Selection.Article {
|
||||
try $0.id()
|
||||
}
|
||||
extension DataService {
|
||||
public func removeLink(objectID: NSManagedObjectID) {
|
||||
// Update CoreData
|
||||
backgroundContext.perform { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let linkedItem = self.backgroundContext.object(with: objectID) as? LinkedItem else { return }
|
||||
linkedItem.remove(inContext: self.backgroundContext)
|
||||
|
||||
public extension DataService {
|
||||
func removeLinkPublisher(
|
||||
itemID: String
|
||||
) -> AnyPublisher<String, BasicError> {
|
||||
// Send update to server
|
||||
self.syncLinkDeletion(itemID: linkedItem.unwrappedID, objectID: objectID)
|
||||
}
|
||||
}
|
||||
|
||||
func syncLinkDeletion(itemID: String, objectID _: NSManagedObjectID) {
|
||||
enum MutationResult {
|
||||
case success(linkId: String)
|
||||
case error(errorCode: Enums.SetBookmarkArticleErrorCode)
|
||||
@ -20,7 +27,9 @@ public extension DataService {
|
||||
try $0.on(
|
||||
setBookmarkArticleSuccess: .init {
|
||||
.success(
|
||||
linkId: try $0.bookmarkedArticle(selection: setBookmarkedArticleSelection)
|
||||
linkId: try $0.bookmarkedArticle(selection: Selection.Article {
|
||||
try $0.id()
|
||||
})
|
||||
)
|
||||
},
|
||||
setBookmarkArticleError: .init { .error(errorCode: try $0.errorCodes().first ?? .notFound) }
|
||||
@ -39,32 +48,24 @@ public extension DataService {
|
||||
|
||||
let path = appEnvironment.graphqlPath
|
||||
let headers = networker.defaultHeaders
|
||||
let context = backgroundContext
|
||||
|
||||
return Deferred {
|
||||
Future { promise in
|
||||
send(mutation, to: path, headers: headers) { result in
|
||||
switch result {
|
||||
case let .success(payload):
|
||||
if payload.errors != nil {
|
||||
promise(.failure(.message(messageText: "Error removing link")))
|
||||
}
|
||||
send(mutation, to: path, headers: headers) { result in
|
||||
let data = try? result.get()
|
||||
let syncStatus: ServerSyncStatus = data == nil ? .needsDeletion : .isNSync
|
||||
|
||||
switch payload.data {
|
||||
case .success:
|
||||
if let linkedItem = LinkedItem.lookup(byID: itemID, inContext: self.backgroundContext) {
|
||||
linkedItem.remove(inContext: self.backgroundContext)
|
||||
}
|
||||
promise(.success(itemID))
|
||||
case .error(errorCode: _):
|
||||
promise(.failure(.message(messageText: "Error removing link")))
|
||||
}
|
||||
case .failure:
|
||||
promise(.failure(.message(messageText: "Error removing link")))
|
||||
}
|
||||
context.perform {
|
||||
guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: context) else { return }
|
||||
linkedItem.serverSyncStatus = Int64(syncStatus.rawValue)
|
||||
|
||||
do {
|
||||
try context.save()
|
||||
logger.debug("LinkedItem deleted succesfully")
|
||||
} catch {
|
||||
context.rollback()
|
||||
logger.debug("Failed to delete LinkedItem: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
.receive(on: DispatchQueue.main)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user