[Fix] Inventory Item Transfer (#1316)

* Fixed so items from the inventory tab of the Party sheet can be dragged out

* Added transfer logic

* Added translation

* Improved item transfer dialog title

* Simplified title

* Updated image

* Simplified the handlebars templates for itemTransfer

* Improved item-identicial check

* Slight improved rendering

* .
This commit is contained in:
WBHarry 2025-11-23 15:04:42 +01:00 committed by GitHub
parent 9f7554cdff
commit 2920ead81a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 228 additions and 47 deletions

View file

@ -1,3 +1,4 @@
import { itemIsIdentical } from '../../../helpers/utils.mjs';
import DHBaseActorSettings from './actor-setting.mjs';
import DHApplicationMixin from './application-mixin.mjs';
@ -217,6 +218,70 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
/* Application Drag/Drop */
/* -------------------------------------------- */
async _onDrop(event) {
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
if (data.originActor === this.document.uuid) return { cancel: true };
/* Handling transfer of inventoryItems */
let cancel = false;
const physicalActorTypes = ['character', 'party'];
if (physicalActorTypes.includes(this.document.type)) {
const originActor = data.originActor ? await foundry.utils.fromUuid(data.originActor) : null;
if (data.originId && originActor && physicalActorTypes.includes(originActor.type)) {
const dropDocument = await foundry.utils.fromUuid(data.uuid);
if (dropDocument.system.metadata.isInventoryItem) {
cancel = true;
if (dropDocument.system.metadata.isQuantifiable) {
const actorItem = originActor.items.get(data.originId);
const quantityTransfered =
actorItem.system.quantity === 1
? 1
: await game.system.api.applications.dialogs.ItemTransferDialog.configure(dropDocument);
if (quantityTransfered) {
if (quantityTransfered === actorItem.system.quantity) {
await originActor.deleteEmbeddedDocuments('Item', [data.originId]);
} else {
cancel = true;
await actorItem.update({
'system.quantity': actorItem.system.quantity - quantityTransfered
});
}
const existingItem = this.document.items.find(x => itemIsIdentical(x, dropDocument));
if (existingItem) {
cancel = true;
await existingItem.update({
'system.quantity': existingItem.system.quantity + quantityTransfered
});
} else {
const createData = dropDocument.toObject();
await this.document.createEmbeddedDocuments('Item', [
{
...createData,
system: {
...createData.system,
quantity: quantityTransfered
}
}
]);
}
} else {
cancel = true;
}
} else {
await originActor.deleteEmbeddedDocuments('Item', [data.originId], { render: false });
const createData = dropDocument.toObject();
await this.document.createEmbeddedDocuments('Item', [createData]);
}
}
}
}
return { cancel };
}
/**
* On dragStart on the item.
* @param {DragEvent} event - The drag event

View file

@ -33,9 +33,9 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
removeResource: DHBaseItemSheet.#removeResource
},
dragDrop: [
{ dragSelector: null, dropSelector: '.tab.features .drop-section' },
{ dragSelector: null, dropSelector: '.drop-section' },
{ dragSelector: '.feature-item', dropSelector: null },
{ dragSelector: '.action-item', dropSelector: null }
{ dragSelector: '.inventory-item', dropSelector: null }
],
contextMenus: [
{
@ -242,37 +242,30 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
* @param {DragEvent} event - The drag event
*/
async _onDragStart(event) {
/* Can prolly be improved a lot, but I don't wanna >_< */
const featureItem = event.currentTarget.closest('.feature-item');
const inventoryItem = event.currentTarget.closest('.inventory-item');
const lineItem = event.currentTarget.closest('.item-line');
const dragItemData = featureItem ?? inventoryItem ?? lineItem;
if (featureItem) {
const feature = this.document.system.features.find(x => x?.id === featureItem.id);
if (!feature) {
const dragItem = await foundry.utils.fromUuid(dragItemData.dataset.itemUuid);
if (dragItem) {
if (!dragItem) {
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.featureIsMissing'));
return;
}
const featureData = { type: 'Item', data: { ...feature.toObject(), _id: null }, fromInternal: true };
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
} else {
const actionItem = event.currentTarget.closest('.action-item');
if (actionItem) {
const action = this.document.system.actions[actionItem.dataset.index];
if (!action) {
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.actionIsMissing'));
return;
}
const actionData = {
type: 'Action',
data: { ...action.toObject(), id: action.id, itemUuid: this.document.uuid },
fromInternal: true
let dragData = {};
if (dragItemData.dataset.type === 'effect')
dragData = {
type: 'ActiveEffect',
fromInternal: this.document.uuid,
data: { ...dragItem, uuid: dragItem.uuid, id: dragItem.id }
};
event.dataTransfer.setData('text/plain', JSON.stringify(actionData));
event.dataTransfer.setDragImage(actionItem.querySelector('img'), 60, 0);
} else {
super._onDragStart(event);
}
else dragData = { type: 'Item', uuid: dragItem.uuid, id: dragItem.id, fromInternal: this.document.id };
event.dataTransfer.setData('text/plain', JSON.stringify(dragData));
event.dataTransfer.setDragImage(dragItemData.querySelector('img'), 60, 0);
}
}
@ -284,7 +277,7 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
super._onDrop(event);
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
if (data.fromInternal) return;
if (data.fromInternal === this.document.id) return;
const target = event.target.closest('fieldset.drop-section');
let item = await fromUuid(data.uuid);