Skip to content
Draft
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
11 changes: 11 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "preview-server",
"runtimeExecutable": "/usr/bin/python3",
"runtimeArgs": ["-m", "http.server", "8765", "--directory", "build/firefox"],
"port": 8765
}
]
}
2 changes: 2 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ function processFile() {
}
case 'preferences.html':
case 'progressWindow.html':
case 'progressWindow_preview.html':
case 'modalPrompt.html':
case 'offscreenSandbox.html':
file.contents = Buffer.from(file.contents.toString()
Expand Down Expand Up @@ -398,6 +399,7 @@ gulp.task('process-custom-scripts', function() {
'./src/browserExt/confirm/confirm.html',
'./src/common/preferences/preferences.html',
'./src/common/progressWindow/progressWindow.html',
'./src/common/progressWindow/progressWindow_preview.html',
'./src/common/modalPrompt/modalPrompt.html',
'./src/browserExt/offscreen/offscreenSandbox.html',
'./src/common/schema.js',
Expand Down
10 changes: 10 additions & 0 deletions src/common/cachedTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,16 @@ Zotero.Connector_Types = new function() {
this.getItemTypeFields = function(typeIdOrName) {
return itemTypes[typeIdOrName][4]/* fields */.slice();
};

this.isMultiline = function(field) {
field = this.getName(field);
var multilineFields = [
'abstractNote',
'extra',
'address'
];
return multilineFields.indexOf(field) != -1;
};
}
};

Expand Down
1 change: 1 addition & 0 deletions src/common/connector.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Zotero.Connector = new function() {
'googleDocsCitationExplorerEnabled',
'supportsAttachmentUpload',
'supportsTagsAutocomplete',
'supportsMetadataUpdates',
'canUserAddNote'
];
for (const key of PREF_KEYS) {
Expand Down
13 changes: 12 additions & 1 deletion src/common/inject/pageSaving.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,16 @@ let PageSaving = {
itemType: item.itemType
}
);

// Send full item data to have progressWindow render it in the itemBox
Zotero.Messaging.sendMessage(
"progressWindow.setItemMetadata",
{
sessionID,
id: item.id,
item
}
);
};
const onTranslatorFallback = (oldTranslator, newTranslator) => {
Zotero.debug(`Saving with ${oldTranslator.label} failed. Trying ${newTranslator.label}`);
Expand Down Expand Up @@ -669,7 +679,8 @@ let PageSaving = {
sessionID: this.sessionDetails.id,
target: data.target,
tags: data.tags,
note: data.note
note: data.note,
updatedMetadata: data.updatedMetadata
}
);

Expand Down
85 changes: 78 additions & 7 deletions src/common/inject/progressWindow_inject.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ if (isTopWindow) {
//
var frameID = 'zotero-progress-window-frame';
var closeOnLeave = false;
var itemBoxOpen = false;
var lastSuccessfulTarget;
var frameReadyDeferred = Zotero.Promise.defer();
var frameInitialized;
Expand Down Expand Up @@ -83,6 +84,57 @@ if (isTopWindow) {
sendMessage(`progressWindowIframe.${name}`, data);
});
}

/**
* Transform a raw translator item into the format expected by the ItemBox component:
* { id, fields: [{name, label, value}], creators: [...], creatorTypes: [{value, label}] }
*
* Field and type labels come from Zotero.Schema.locale (en-US locale from schema.json),
* stored during Zotero.Schema.init() in schema.js.
*/
function formatItemMetadata(id, item) {
let locale = Zotero.Schema.locale || {};
let fieldLocale = locale.fields || {};
let itemTypeLocale = locale.itemTypes || {};
let creatorTypeLocale = locale.creatorTypes || {};

let itemTypeID = Zotero.ItemTypes.getID(item.itemType);
let fieldIDs = Zotero.ItemFields.getItemTypeFields(itemTypeID);

let fields = [
{
name: 'itemType',
label: Zotero.getString("progressWindow_itemBox_itemType"),
value: itemTypeLocale[item.itemType] || item.itemType
}
];
for (let fieldID of fieldIDs) {
let fieldName = Zotero.ItemFields.getName(fieldID);
let value = item[fieldName];
let field = {
name: fieldName,
label: fieldLocale[fieldName] || fieldName,
value: (value != null && value !== '') ? String(value) : ''
};
if (Zotero.ItemFields.isMultiline(fieldID)) {
field.multiline = true;
}
fields.push(field);
}

let creatorTypeObjs = Zotero.CreatorTypes.getTypesForItemType(itemTypeID);
let creatorTypes = creatorTypeObjs.map(ct => ({
value: ct.name,
label: creatorTypeLocale[ct.name] || ct.name
}));

return {
id,
fields,
creators: item.creators || [],
creatorTypes
};
}

function changeHeadline() {
isReadOnly = arguments.length <= 2;
Expand Down Expand Up @@ -225,8 +277,10 @@ if (isTopWindow) {
// Don't start the timer if the mouse is over the popup or the tags box has focus
if (insideIframe) return;
if (closeTimerDisabled) return;

if (!delay) delay = 5000;
// Give the user more time if they have the item box open
if (itemBoxOpen) delay = Math.max(delay, 20000);
stopCloseTimer();
closeTimeoutID = setTimeout(hideFrame, delay);
}
Expand Down Expand Up @@ -298,7 +352,12 @@ if (isTopWindow) {
// If we're making changes, don't close the popup and keep delaying syncs
stopCloseTimer();
blurred = false;


// If target selector hasn't been used yet, data.target may be undefined.
// Use lastSuccessfulTarget as fallback.
if (!data.target && !lastSuccessfulTarget) return;
var target = data.target || lastSuccessfulTarget;

// If the session isn't yet registered or a session update is in progress,
// store the data to run after, overwriting any already-queued data
if (!createdSessions.has(currentSessionID) || updatingSession) {
Expand All @@ -311,11 +370,12 @@ if (isTopWindow) {
await sendMessage(
"updateSession",
{
target: data.target.id,
target: target.id,
tags: data.tags,
updatedMetadata: data.updatedMetadata,
note: data.note.replace(/\n/g, "<br>"), // replace newlines with <br> for note-editor
resaveAttachments: !lastSuccessfulTarget.filesEditable && data.target.filesEditable,
removeAttachments: lastSuccessfulTarget.filesEditable && !data.target.filesEditable
resaveAttachments: !lastSuccessfulTarget.filesEditable && target.filesEditable,
removeAttachments: lastSuccessfulTarget.filesEditable && !target.filesEditable
}
);
}
Expand All @@ -335,7 +395,7 @@ if (isTopWindow) {
}

// Keep track of last successful target to show on reopen and failure
lastSuccessfulTarget = data.target;
lastSuccessfulTarget = target;
};

// Once a session is created in the client, send any queued session data
Expand All @@ -358,6 +418,7 @@ if (isTopWindow) {

addMessageListener('progressWindowIframe.disableCloseTimer', () => closeTimerDisabled = true);
addMessageListener('progressWindowIframe.enableCloseTimer', () => closeTimerDisabled = false);
addMessageListener('progressWindowIframe.itemBoxToggled', (data) => { itemBoxOpen = data.open; });

addMessageListener('progressWindowIframe.blurred', async function() {
blurred = true;
Expand All @@ -366,7 +427,12 @@ if (isTopWindow) {
// (i.e., they didn't just switch to another window)
await Zotero.Promise.delay(150);
if (lastClick > new Date() - 500) {
hideFrame();
if (itemBoxOpen) {
startCloseTimer(20000);
}
else {
hideFrame();
}
}
});

Expand Down Expand Up @@ -467,6 +533,11 @@ if (isTopWindow) {
addEvent("updateProgress", [data.id, data]);
});

Zotero.Messaging.addMessageListener("progressWindow.setItemMetadata", (data) => {
if (data.sessionID && data.sessionID != currentSessionID) return;
addEvent("setItemMetadata", [formatItemMetadata(data.id, data.item)]);
});

Zotero.Messaging.addMessageListener("progressWindow.close", function () {
// Mark frame as hidden so that if this is called after a progressWindow.show but before
// the popup has been initialized (e.g., when displaying the Select Items dialog) it's
Expand Down
3 changes: 3 additions & 0 deletions src/common/progressWindow/chevron-8.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/common/progressWindow/input-dual.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/common/progressWindow/input-single.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/common/progressWindow/minus-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/common/progressWindow/plus-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading