diff --git a/chrome/content/zotero/elements/attachmentBox.js b/chrome/content/zotero/elements/attachmentBox.js index a07260c26d..edaf5b2dac 100644 --- a/chrome/content/zotero/elements/attachmentBox.js +++ b/chrome/content/zotero/elements/attachmentBox.js @@ -93,6 +93,8 @@ this._preview = null; this._isRendering = false; + + this._isEditingFilename = false; } get mode() { @@ -204,8 +206,13 @@ this._id('url-menu').openPopupAtScreen(event.screenX, event.screenY, true); }); - this._id("fileName").addEventListener('blur', () => { - this.editFileName(this._id("fileName").value); + let fileName = this._id("fileName"); + fileName.addEventListener('focus', () => { + this._isEditingFilename = true; + }); + fileName.addEventListener('blur', () => { + this.editFileName(fileName.value); + this._isEditingFilename = false; }); this._preview = this._id("attachment-preview"); @@ -280,6 +287,8 @@ } Zotero.debug('Refreshing attachment box'); this._isRendering = true; + // Cancel editing filename when refreshing + this._isEditingFilename = false; if (this.usePreview) { this._preview.item = this.item; @@ -350,7 +359,7 @@ else { fileNameRow.hidden = true; } - this._id("fileName").readonly = !this.editable; + this._id("fileName").toggleAttribute("readonly", (!this.editable || !fileExists)); // Page count if (this.displayPages && this._item.isPDFAttachment()) { @@ -486,18 +495,48 @@ } async editFileName(newFilename) { + if (!this._isEditingFilename) { + return; + } let item = this.item; // Rename associated file let nsIPS = Services.prompt; + let getExtension = function (filename) { + const extRegex = /\.\w{1,10}$/; + if (extRegex.test(filename)) { + return filename.match(extRegex)[0]; + } + return ""; + }; newFilename = newFilename.trim(); let oldFilename = item.getFilename(); if (oldFilename === newFilename) { return; } - if (newFilename.search(/\.\w{1,10}$/) == -1) { + // Don't allow empty filename + if (!newFilename) { + this.render(); + return; + } + let newExt = getExtension(newFilename); + let oldExt = getExtension(oldFilename); + if (!newExt && oldExt) { // User did not specify extension. Use current - let oldExt = oldFilename.match(/\.\w{1,10}$/); - if (oldExt) newFilename += oldExt[0]; + newFilename += oldExt; + newExt = oldExt; + } + if (newExt !== oldExt && oldExt) { + // User changed extension. Confirm + let index = Zotero.Prompt.confirm({ + window, + title: Zotero.getString('general.warning'), + text: Zotero.getString('pane.item.attachments.rename.confirmExtChange.text', [oldExt, newExt, Zotero.appName]), + button0: Zotero.getString('pane.item.attachments.rename.confirmExtChange.keep', oldExt), + button1: Zotero.getString('pane.item.attachments.rename.confirmExtChange.change', newExt), + }); + if (index == 0) { + newFilename = newFilename.replace(/\.\w{1,10}$/, oldExt); + } } let renamed = await item.renameAttachmentFile(newFilename); if (renamed == -1) { diff --git a/chrome/content/zotero/xpcom/prompt.js b/chrome/content/zotero/xpcom/prompt.js index f6c8e2a03d..b3f30068f6 100644 --- a/chrome/content/zotero/xpcom/prompt.js +++ b/chrome/content/zotero/xpcom/prompt.js @@ -81,7 +81,7 @@ Zotero.Prompt = { typeof button0 == 'number' ? null : button0, typeof button1 == 'number' ? null : button1, typeof button2 == 'number' ? null : button2, - checkLabel, checkbox + checkLabel, typeof checkbox == 'object' ? checkbox : {} ); } -}; \ No newline at end of file +}; diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties index 3b11a4e37f..5fd5e0225c 100644 --- a/chrome/locale/en-US/zotero/zotero.properties +++ b/chrome/locale/en-US/zotero/zotero.properties @@ -418,6 +418,9 @@ pane.item.notes.ignoreMissingImage = Some note images are missing and cannot be pane.item.attachments.rename.title = New title: pane.item.attachments.rename.renameAssociatedFile = Rename associated file pane.item.attachments.rename.error = An error occurred while renaming the file. +pane.item.attachments.rename.confirmExtChange.text = Are you sure you want to change the file extension from ā€œ%Sā€ to ā€œ%Sā€?\n\nIf you change the extension, the file may open with a different application outside of %S. +pane.item.attachments.rename.confirmExtChange.keep = Keep %S +pane.item.attachments.rename.confirmExtChange.change = Use %S pane.item.attachments.fileNotFound.title = File Not Found pane.item.attachments.fileNotFound.text1 = The attached file could not be found. pane.item.attachments.fileNotFound.text1.path = The attached file could not be found at the following path: