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

Improve attachment move to/from parent actions #1072

Merged
merged 3 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,20 @@ struct CancelParentCreationDbRequest: DbRequest {

func process(in database: Realm) throws {
guard let item = database.objects(RItem.self).uniqueObject(key: key, libraryId: libraryId), item.parent != nil else { return }
let parentCollections = item.parent?.collections
item.parent = nil
let parentChange = item.changes.filter { change in
return change.rawChanges == RItemChanges.parent.rawValue
}
// Move item back to removed parent's collections.
if let parentCollections, !parentCollections.isEmpty {
for collection in parentCollections {
if collection.items.filter(.key(key)).first == nil {
collection.items.append(item)
item.changes.append(RObjectChange.create(changes: RItemChanges.collections))
}
}
}
item.changesSyncPaused = false
database.delete(parentChange)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct CreateItemFromDetailDbRequest: DbResponseRequest {

let key: String
let libraryId: LibraryIdentifier
let collectionKey: String?
let collectionsSource: ItemDetailState.DetailType.CollectionsSource?
let data: ItemDetailState.Data
let attachments: [Attachment]
let notes: [Note]
Expand Down Expand Up @@ -50,10 +50,21 @@ struct CreateItemFromDetailDbRequest: DbResponseRequest {

var changes: RItemChanges = [.type, .fields]

if let key = self.collectionKey,
let collection = database.objects(RCollection.self).uniqueObject(key: key, libraryId: libraryId) {
collection.items.append(item)
changes.insert(.collections)
var useCollectionsFromChildren = false
switch collectionsSource {
case .collectionKeys(let keys):
for key in keys {
if let collection = database.objects(RCollection.self).uniqueObject(key: key, libraryId: libraryId) {
collection.items.append(item)
changes.insert(.collections)
}
}

case .fromChildren:
useCollectionsFromChildren = true

case .none:
break
}

// Create creators
Expand Down Expand Up @@ -118,6 +129,21 @@ struct CreateItemFromDetailDbRequest: DbResponseRequest {
rAttachment.parent = item
rAttachment.changes.append(RObjectChange.create(changes: RItemChanges.parent))
rAttachment.changeType = .user
if useCollectionsFromChildren, !rAttachment.collections.isEmpty {
for collection in rAttachment.collections {
// Remove attachment from this collection, if needed.
if let index = collection.items.index(of: rAttachment) {
collection.items.remove(at: index)
rAttachment.changes.append(RObjectChange.create(changes: RItemChanges.collections))
}
// Append parent to this collection, if needed.
if collection.items.filter(.key(key)).first == nil {
collection.items.append(item)
changes.insert(.collections)
}
}
}

rAttachment.changesSyncPaused = true
} else {
let rAttachment = try CreateAttachmentDbRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,15 @@ struct MoveItemsToParentDbRequest: DbRequest {

if !item.collections.isEmpty {
for collection in item.collections {
guard let index = collection.items.index(of: item) else { continue }
collection.items.remove(at: index)
// Remove item from this collection, if needed.
if let index = collection.items.index(of: item) {
collection.items.remove(at: index)
}
// Append parent to this collection, if needed.
if collection.items.filter(.key(parent.key)).first == nil {
collection.items.append(parent)
parent.changes.append(RObjectChange.create(changes: RItemChanges.collections))
}
}
changes.insert(.collections)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,24 @@ struct RemoveItemFromParentDbRequest: DbRequest {

func process(in database: Realm) throws {
guard let item = database.objects(RItem.self).uniqueObject(key: key, libraryId: libraryId), item.parent != nil else { return }
let parentCollections = item.parent?.collections

// Update the parent item, so that it's updated in the item list to hide attachment/note marker
item.parent?.baseTitle = item.parent?.baseTitle ?? ""
item.parent?.changeType = .user
item.parent = nil
item.changes.append(RObjectChange.create(changes: RItemChanges.parent))

// Move item to removed parent collections.
if let parentCollections, !parentCollections.isEmpty {
for collection in parentCollections {
if collection.items.filter(.key(key)).first == nil {
collection.items.append(item)
item.changes.append(RObjectChange.create(changes: RItemChanges.collections))
}
}
}

item.changeType = .user
}
}
8 changes: 4 additions & 4 deletions Zotero/Scenes/Detail/DetailCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -414,16 +414,16 @@ extension DetailCoordinator: DetailItemsCoordinatorDelegate {

controller.addAction(UIAlertAction(title: L10n.Items.new, style: .default, handler: { [weak self, weak viewModel] _ in
guard let self, let viewModel else { return }
let collectionKey: String?
let collectionsSource: ItemDetailState.DetailType.CollectionsSource?
switch viewModel.state.collection.identifier {
case .collection(let key):
collectionKey = key
collectionsSource = .collectionKeys([key])

case .search, .custom:
collectionKey = nil
collectionsSource = nil
}
showTypePicker(selected: "") { [weak self] type in
self?.showItemDetail(for: .creation(type: type, child: nil, collectionKey: collectionKey), libraryId: viewModel.state.library.identifier, scrolledToKey: nil, animated: true)
self?.showItemDetail(for: .creation(type: type, child: nil, collectionsSource: collectionsSource), libraryId: viewModel.state.library.identifier, scrolledToKey: nil, animated: true)
}
}))

Expand Down
7 changes: 6 additions & 1 deletion Zotero/Scenes/Detail/ItemDetail/Models/ItemDetailState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ struct ItemDetailState: ViewModelState {
}

enum DetailType {
case creation(type: String, child: Attachment?, collectionKey: String?)
enum CollectionsSource {
case collectionKeys([String])
case fromChildren
}

case creation(type: String, child: Attachment?, collectionsSource: CollectionsSource?)
case duplication(itemKey: String, collectionKey: String?)
case preview(key: String)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ final class ItemDetailActionHandler: ViewModelActionHandler, BackgroundDbProcess

private func loadInitialData(in viewModel: ViewModel<ItemDetailActionHandler>) {
let library: Library
var collectionKey: String?
var collectionsSource: ItemDetailState.DetailType.CollectionsSource?
var data: (data: ItemDetailState.Data, attachments: [Attachment], notes: [Note], tags: [Tag])

do {
Expand All @@ -173,8 +173,8 @@ final class ItemDetailActionHandler: ViewModelActionHandler, BackgroundDbProcess
}

switch viewModel.state.type {
case .creation(let itemType, let child, let _collectionKey):
collectionKey = _collectionKey
case .creation(let itemType, let child, let _collectionsSource):
collectionsSource = _collectionsSource
data = try ItemDetailDataCreator.createData(
from: .new(itemType: itemType, child: child),
schemaController: self.schemaController,
Expand All @@ -185,8 +185,8 @@ final class ItemDetailActionHandler: ViewModelActionHandler, BackgroundDbProcess
doiDetector: FieldKeys.Item.isDoi
)

case .duplication(let itemKey, let _collectionKey):
collectionKey = _collectionKey
case .duplication(let itemKey, let collectionKey):
collectionsSource = collectionKey.flatMap({ .collectionKeys([$0]) })
let item = try self.dbStorage.perform(request: ReadItemDbRequest(libraryId: library.identifier, key: itemKey), on: .main)
data = try ItemDetailDataCreator.createData(
from: .existing(item: item, ignoreChildren: true),
Expand All @@ -213,7 +213,7 @@ final class ItemDetailActionHandler: ViewModelActionHandler, BackgroundDbProcess
let request = CreateItemFromDetailDbRequest(
key: viewModel.state.key,
libraryId: library.identifier,
collectionKey: collectionKey,
collectionsSource: collectionsSource,
data: data.data,
attachments: data.attachments,
notes: data.notes,
Expand Down
3 changes: 1 addition & 2 deletions Zotero/Scenes/Detail/Items/Views/ItemsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,8 @@ final class ItemsViewController: BaseItemsViewController {

case .createParent:
guard let key = selectedKeys.first, case .attachment(let attachment, _) = viewModel.state.itemAccessories[key] else { return }
let collectionKey = collection.identifier.key
coordinatorDelegate?.showItemDetail(
for: .creation(type: ItemTypes.document, child: attachment, collectionKey: collectionKey),
for: .creation(type: ItemTypes.document, child: attachment, collectionsSource: .fromChildren),
libraryId: library.identifier,
scrolledToKey: nil,
animated: true
Expand Down