Add FilePicker module to replace nsIFilePicker

`nsIFilePicker::show()` is removed in Firefox 60 in favor of `open()`,
which takes a callback (and apparently has been preferred for a long
time).

There's no point switching to that, so this module is a version of
nsIFilePicker with an async `show()` that returns a promise and some
XPCOM-isms replaced (e.g., string paths instead of nsIFile).
This commit is contained in:
Dan Stillman 2019-08-24 04:25:51 -04:00
parent ee5302f893
commit 6f965251ed
13 changed files with 377 additions and 190 deletions

View file

@ -24,6 +24,7 @@
*/ */
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
import FilePicker from 'zotero/filePicker';
var Zotero = Components.classes["@zotero.org/Zotero;1"] var Zotero = Components.classes["@zotero.org/Zotero;1"]
// Currently uses only nsISupports // Currently uses only nsISupports
@ -70,7 +71,7 @@ var Scaffold = new function() {
'textbox-hidden-prefs':'hiddenPrefs' 'textbox-hidden-prefs':'hiddenPrefs'
}; };
this.onLoad = function (e) { this.onLoad = async function (e) {
if(e.target !== document) return; if(e.target !== document) return;
_document = document; _document = document;
@ -145,7 +146,7 @@ var Scaffold = new function() {
} }
if (!Scaffold_Translators.getDirectory()) { if (!Scaffold_Translators.getDirectory()) {
if (!this.promptForTranslatorsDirectory()) { if (!await this.promptForTranslatorsDirectory()) {
window.close(); window.close();
return; return;
} }
@ -155,7 +156,7 @@ var Scaffold = new function() {
_translatorProvider = Scaffold_Translators.getProvider(); _translatorProvider = Scaffold_Translators.getProvider();
}; };
this.promptForTranslatorsDirectory = function () { this.promptForTranslatorsDirectory = async function () {
var ps = Services.prompt; var ps = Services.prompt;
var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING
+ ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING + ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING
@ -171,7 +172,7 @@ var Scaffold = new function() {
); );
// Revert to home directory // Revert to home directory
if (index == 0) { if (index == 0) {
let dir = this.setTranslatorsDirectory(); let dir = await this.setTranslatorsDirectory();
if (dir) { if (dir) {
return true; return true;
} }
@ -182,23 +183,22 @@ var Scaffold = new function() {
return false; return false;
}; };
this.setTranslatorsDirectory = function () { this.setTranslatorsDirectory = async function () {
var nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
var oldPath = Zotero.Prefs.get('scaffold.translatorsDir'); var oldPath = Zotero.Prefs.get('scaffold.translatorsDir');
if (oldPath) { if (oldPath) {
fp.displayDirectory = Zotero.File.pathToFile(oldPath); fp.displayDirectory = oldPath;
} }
fp.init( fp.init(
window, window,
"Select Translators Directory", "Select Translators Directory",
nsIFilePicker.modeGetFolder fp.modeGetFolder
); );
fp.appendFilters(nsIFilePicker.filterAll); fp.appendFilters(fp.filterAll);
if (fp.show() != nsIFilePicker.returnOK) { if (await fp.show() != fp.returnOK) {
return false; return false;
} }
var path = OS.Path.normalize(fp.file.path); var path = OS.Path.normalize(fp.file);
if (oldPath == path) { if (oldPath == path) {
return false; return false;
} }

View file

@ -24,6 +24,7 @@
*/ */
Components.utils.import("resource://gre/modules/osfile.jsm") Components.utils.import("resource://gre/modules/osfile.jsm")
import FilePicker from 'zotero/filePicker';
/****Zotero_File_Exporter**** /****Zotero_File_Exporter****
** **
@ -44,9 +45,9 @@ var Zotero_File_Exporter = function() {
* *
* @return {Promise} * @return {Promise}
**/ **/
Zotero_File_Exporter.prototype.save = Zotero.Promise.coroutine(function* () { Zotero_File_Exporter.prototype.save = async function () {
var translation = new Zotero.Translate.Export(); var translation = new Zotero.Translate.Export();
var translators = yield translation.getTranslators(); var translators = await translation.getTranslators();
// present options dialog // present options dialog
var io = {translators:translators} var io = {translators:translators}
@ -56,17 +57,15 @@ Zotero_File_Exporter.prototype.save = Zotero.Promise.coroutine(function* () {
return false; return false;
} }
const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString("fileInterface.export"), fp.modeSave);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString("fileInterface.export"), nsIFilePicker.modeSave);
// set file name and extension // set file name and extension
if(io.displayOptions.exportFileData) { if(io.displayOptions.exportFileData) {
// if the result will be a folder, don't append any extension or use // if the result will be a folder, don't append any extension or use
// filters // filters
fp.defaultString = this.name; fp.defaultString = this.name;
fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll); fp.appendFilters(fp.filterAll);
} else { } else {
// if the result will be a file, append an extension and use filters // if the result will be a file, append an extension and use filters
fp.defaultString = this.name+(io.selectedTranslator.target ? "."+io.selectedTranslator.target : ""); fp.defaultString = this.name+(io.selectedTranslator.target ? "."+io.selectedTranslator.target : "");
@ -74,8 +73,8 @@ Zotero_File_Exporter.prototype.save = Zotero.Promise.coroutine(function* () {
fp.appendFilter(io.selectedTranslator.label, "*."+(io.selectedTranslator.target ? io.selectedTranslator.target : "*")); fp.appendFilter(io.selectedTranslator.label, "*."+(io.selectedTranslator.target ? io.selectedTranslator.target : "*"));
} }
var rv = fp.show(); var rv = await fp.show();
if (rv != nsIFilePicker.returnOK && rv != nsIFilePicker.returnReplace) { if (rv != fp.returnOK && rv != fp.returnReplace) {
return; return;
} }
@ -89,7 +88,7 @@ Zotero_File_Exporter.prototype.save = Zotero.Promise.coroutine(function* () {
translation.setLibraryID(this.libraryID); translation.setLibraryID(this.libraryID);
} }
translation.setLocation(fp.file); translation.setLocation(Zotero.File.pathToFile(fp.file));
translation.setTranslator(io.selectedTranslator); translation.setTranslator(io.selectedTranslator);
translation.setDisplayOptions(io.displayOptions); translation.setDisplayOptions(io.displayOptions);
translation.setHandler("itemDone", function () { translation.setHandler("itemDone", function () {
@ -100,7 +99,7 @@ Zotero_File_Exporter.prototype.save = Zotero.Promise.coroutine(function* () {
Zotero.getString("fileInterface.itemsExported") Zotero.getString("fileInterface.itemsExported")
); );
translation.translate() translation.translate()
}); };
/* /*
* Closes the items exported indicator * Closes the items exported indicator
@ -593,7 +592,7 @@ var Zotero_File_Interface = new function() {
/** /**
* Creates a bibliography from a collection or saved search * Creates a bibliography from a collection or saved search
*/ */
this.bibliographyFromCollection = function () { this.bibliographyFromCollection = async function () {
var items = ZoteroPane.getSortedItems(); var items = ZoteroPane.getSortedItems();
// Find collection name // Find collection name
@ -609,17 +608,17 @@ var Zotero_File_Interface = new function() {
} }
} }
_doBibliographyOptions(name, items); await _doBibliographyOptions(name, items);
} }
/* /*
* Creates a bibliography from a items * Creates a bibliography from a items
*/ */
function bibliographyFromItems() { async function bibliographyFromItems() {
var items = ZoteroPane_Local.getSelectedItems(); var items = ZoteroPane_Local.getSelectedItems();
if(!items || !items.length) throw("no items currently selected"); if(!items || !items.length) throw("no items currently selected");
_doBibliographyOptions(Zotero.getString("fileInterface.untitledBibliography"), items); await _doBibliographyOptions(Zotero.getString("fileInterface.untitledBibliography"), items);
} }
@ -688,7 +687,7 @@ var Zotero_File_Interface = new function() {
/* /*
* Shows bibliography options and creates a bibliography * Shows bibliography options and creates a bibliography
*/ */
function _doBibliographyOptions(name, items) { async function _doBibliographyOptions(name, items) {
// make sure at least one item is not a standalone note or attachment // make sure at least one item is not a standalone note or attachment
var haveRegularItem = false; var haveRegularItem = false;
for (let item of items) { for (let item of items) {
@ -779,7 +778,7 @@ var Zotero_File_Interface = new function() {
browser.loadURIWithFlags("data:text/html;charset=utf-8,"+encodeURI(bibliography), browser.loadURIWithFlags("data:text/html;charset=utf-8,"+encodeURI(bibliography),
Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY, null, "utf-8", null); Components.interfaces.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY, null, "utf-8", null);
} else if(io.method == "save-as-html") { } else if(io.method == "save-as-html") {
var fStream = _saveBibliography(name, "HTML"); let fStream = await _saveBibliography(name, "HTML");
if(fStream !== false) { if(fStream !== false) {
var html = ""; var html = "";
@ -805,7 +804,7 @@ var Zotero_File_Interface = new function() {
fStream.close(); fStream.close();
} }
} else if(io.method == "save-as-rtf") { } else if(io.method == "save-as-rtf") {
var fStream = _saveBibliography(name, "RTF"); let fStream = await _saveBibliography(name, "RTF");
if(fStream !== false) { if(fStream !== false) {
fStream.write(bibliography, bibliography.length); fStream.write(bibliography, bibliography.length);
fStream.close(); fStream.close();
@ -814,29 +813,31 @@ var Zotero_File_Interface = new function() {
} }
function _saveBibliography(name, format) { async function _saveBibliography(name, format) {
// saveable bibliography, using a file stream // saveable bibliography, using a file stream
const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, "Save Bibliography", fp.modeSave);
.createInstance(nsIFilePicker);
fp.init(window, "Save Bibliography", nsIFilePicker.modeSave);
if(format == "RTF") { if(format == "RTF") {
var extension = "rtf"; var extension = "rtf";
fp.appendFilter("RTF", "*.rtf"); fp.appendFilter("RTF", "*.rtf");
} else { } else {
var extension = "html"; var extension = "html";
fp.appendFilters(nsIFilePicker.filterHTML); fp.appendFilters(fp.filterHTML);
} }
fp.defaultString = name+"."+extension; fp.defaultString = name+"."+extension;
var rv = fp.show(); var rv = await fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { if (rv == fp.returnOK || rv == fp.returnReplace) {
// open file // open file
var fStream = Components.classes["@mozilla.org/network/file-output-stream;1"]. var fStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream); createInstance(Components.interfaces.nsIFileOutputStream);
fStream.init(fp.file, 0x02 | 0x08 | 0x20, 0o664, 0); // write, create, truncate fStream.init(
Zotero.File.pathToFile(fp.file),
0x02 | 0x08 | 0x20, 0o664, // write, create, truncate
0
);
return fStream; return fStream;
} else { } else {
return false; return false;

View file

@ -1,3 +1,5 @@
import FilePicker from 'zotero/filePicker';
var Zotero_Import_Wizard = { var Zotero_Import_Wizard = {
_wizard: null, _wizard: null,
_dbs: null, _dbs: null,
@ -95,12 +97,10 @@ var Zotero_Import_Wizard = {
chooseFile: async function (translation) { chooseFile: async function (translation) {
var translation = new Zotero.Translate.Import(); var translation = new Zotero.Translate.Import();
var translators = await translation.getTranslators(); var translators = await translation.getTranslators();
const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString("fileInterface.import"), fp.modeOpen);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString("fileInterface.import"), nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterAll); fp.appendFilters(fp.filterAll);
var collation = Zotero.getLocaleCollation(); var collation = Zotero.getLocaleCollation();
@ -117,14 +117,14 @@ var Zotero_Import_Wizard = {
fp.appendFilter(filter.label, "*." + filter.target); fp.appendFilter(filter.label, "*." + filter.target);
} }
var rv = fp.show(); var rv = await fp.show();
if (rv !== nsIFilePicker.returnOK && rv !== nsIFilePicker.returnReplace) { if (rv !== fp.returnOK && rv !== fp.returnReplace) {
return false; return false;
} }
Zotero.debug(`File is ${fp.file.path}`); Zotero.debug(`File is ${fp.file}`);
this._file = fp.file.path; this._file = fp.file;
this._wizard.canAdvance = true; this._wizard.canAdvance = true;
this._wizard.goTo('page-options'); this._wizard.goTo('page-options');
}, },
@ -151,16 +151,14 @@ var Zotero_Import_Wizard = {
*/ */
chooseMendeleyDB: async function () { chooseMendeleyDB: async function () {
document.getElementById('file-list').selectedIndex = -1; document.getElementById('file-list').selectedIndex = -1;
const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString('fileInterface.import'), fp.modeOpen);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString('fileInterface.import'), nsIFilePicker.modeOpen);
fp.appendFilter("Mendeley Database", "*.sqlite"); // TODO: Localize fp.appendFilter("Mendeley Database", "*.sqlite"); // TODO: Localize
var rv = fp.show(); var rv = await fp.show();
if (rv != nsIFilePicker.returnOK) { if (rv != fp.returnOK) {
return false; return false;
} }
this._file = fp.file.path; this._file = fp.file;
this._wizard.canAdvance = true; this._wizard.canAdvance = true;
this._wizard.advance(); this._wizard.advance();
}, },

View file

@ -0,0 +1,201 @@
import { Cc, Ci, Cu } from 'chrome';
Cu.import("resource://gre/modules/osfile.jsm");
/**
* Interface to the system filepicker.
*
* Based on Mozilla's nsIFilePicker, with minor modifications (e.g., strings paths instead nsIFile,
* promise-returning show()).
*
* @class
*/
class FilePicker {
constructor() {
this._fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
}
/**
* @param {Window} parentWindow
* @param {String} title
* @param {Integer} mode - One of the mode constants, indicating the type of picker to create
*/
init(parentWindow, title, mode) {
this._fp.init(parentWindow, title, mode);
};
/**
* Appends a custom file extension filter to the dialog. The filter appended first will be used when
* the dialog is initially opened. The user may then select another from the list.
*
* @param {String} title - The title of the filter
* @param {String} filter - The filter string. Multiple extensions may be included, separated by a
* semicolon and a space.
*/
appendFilter(title, filter) {
this._fp.appendFilter(title, filter);
};
/**
* Appends a list of file extension filters, from the predefined list, to the dialog
*
* @param {Integer} filterMask - A combination of the filters you wish to use. You may OR multiple
* filters together; for example <code>filterAll | filterHTML</code>.
*/
appendFilters(filterMask) {
this._fp.appendFilters(filterMask);
};
/**
* Show the dialog
*
* @return {Promise<Integer>} One of the return constants
*/
async show() {
return new Zotero.Promise(function (resolve) {
this._fp.open(returnConstant => resolve(returnConstant));
}.bind(this));
};
};
/** @const {Integer} FilePicker#modeOpen - Load a file */
/** @const {Integer} FilePicker#modeSave - Save a file */
/** @const {Integer} FilePicker#modeGetFolder - Select a folder/directory */
/** @const {Integer} FilePicker#modeOpenMultiple - Load multiple files */
FilePicker.prototype.modeOpen = 0;
FilePicker.prototype.modeSave = 1;
FilePicker.prototype.modeGetFolder = 2;
FilePicker.prototype.modeOpenMultiple = 3;
/** @const {Integer} FilePicker#returnOK - The file picker dialog was closed by the user hitting 'OK' */
/** @const {Integer} FilePicker#returnCancel - The file picker dialog was closed by the user hitting 'Cancel' */
/** @const {Integer} FilePicker#returnReplace - The user chose an existing file and acknowledged that they want to overwrite the file */
FilePicker.prototype.returnOK = 0;
FilePicker.prototype.returnCancel = 1;
FilePicker.prototype.returnReplace = 2;
/** @const {Integer} FilePicker#filterAll - All files */
/** @const {Integer} FilePicker#filterHTML - HTML files */
/** @const {Integer} FilePicker#filterText - Text files */
/** @const {Integer} FilePicker#filterImages - Image files */
/** @const {Integer} FilePicker#filterXML - XML files */
/** @const {Integer} FilePicker#filterApps - Platform-specific application filter */
/** @const {Integer} FilePicker#filterAllowURLs - Allow URLs */
/** @const {Integer} FilePicker#filterAudio - Audio files */
/** @const {Integer} FilePicker#filterVideo - Video files */
FilePicker.prototype.filterAll = 0x001;
FilePicker.prototype.filterHTML = 0x002;
FilePicker.prototype.filterText = 0x004;
FilePicker.prototype.filterImages = 0x008;
FilePicker.prototype.filterXML = 0x010;
FilePicker.prototype.filterApps = 0x040;
FilePicker.prototype.filterAllowURLs = 0x80;
FilePicker.prototype.filterAudio = 0x100;
FilePicker.prototype.filterVideo = 0x200;
['addToRecentDocs', 'defaultExtension', 'defaultString', 'displayDirectory', 'filterIndex'].forEach((prop) => {
/**
* @name FilePicker#addToRecentDocs
* @type Boolean
* @default false
* @desc If true, the file is added to the operating system's "recent documents" list (if the
* operating system has one; nothing happens if there is no such concept on the user's platform).
*/
/**
* @name FilePicker#defaultExtension
* @type String
* @desc The extension for the type of files you want to work with. On some platforms, this is
* automatically appended to filenames the user enters, if required. Specify it without a
* leading dot, for example "jpg".
*/
/**
* @name FilePicker#defaultString
* @type String
* @desc The filename, including extension, that should be suggested to the user as a default.
* This should be set before calling show().
*/
/**
* @name FilePicker#displayDirectory
* @type String
* @desc The filename, including extension, that should be suggested to the user as a default.
* This should be set before calling show().
*/
/**
* @name FilePicker#filterIndex
* @type Integer
* @desc The (0-based) index of the filter which is currently selected in the file picker dialog.
* Set this to choose a particular filter to be selected by default.
*/
Object.defineProperty(FilePicker.prototype, prop, {
// TODO: Others
get: function () {
var val = this._fp[prop];
if (prop == 'displayDirectory') {
// Convert from nsIFile
val = val.path;
}
return val;
},
set: function (val) {
if (prop == 'displayDirectory') {
// Convert to nsIFile
val = Zotero.File.pathToFile(val);
}
this._fp[prop] = val;
},
enumerable: true
});
});
// Read-only properties
['file', 'files', 'fileURL'].forEach((prop) => {
/**
* @name FilePicker#file
* @type String
* @readonly
* @desc The selected file or directory.
*/
/**
* @name FilePicker#files
* @type String[]
* @readonly
* @desc An array of the selected files. Only works with `modeOpenMultiple` mode.
*/
/**
* @name FilePicker#fileURL
* @type String
* @readonly
* @desc The URI of the selected file or directory.
*/
Object.defineProperty(FilePicker.prototype, prop, {
get: function () {
var val = this._fp[prop];
switch (prop) {
case 'file':
// Convert from nsIFile
val = OS.Path.normalize(val.path);
break;
case 'files':
var files = [];
while (val.hasMoreElements()) {
let file = val.getNext();
file.QueryInterface(Ci.nsIFile);
files.push(file.path);
}
val = files;
break;
case 'fileURL':
val = val.spec;
break;
}
return val;
},
enumerable: true
});
});
Object.freeze(FilePicker.prototype);
export default FilePicker;

View file

@ -24,6 +24,7 @@
*/ */
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
import FilePicker from 'zotero/filePicker';
Zotero_Preferences.Advanced = { Zotero_Preferences.Advanced = {
_openURLResolvers: null, _openURLResolvers: null,
@ -554,25 +555,20 @@ Zotero_Preferences.Attachment_Base_Directory = {
}, },
choosePath: Zotero.Promise.coroutine(function* () { choosePath: async function () {
var oldPath = this.getPath(); var oldPath = this.getPath();
//Prompt user to choose new base path //Prompt user to choose new base path
var fp = new FilePicker();
if (oldPath) { if (oldPath) {
var oldPathFile = Zotero.File.pathToFile(oldPath); fp.displayDirectory = oldPath;
} }
var nsIFilePicker = Components.interfaces.nsIFilePicker; fp.init(window, Zotero.getString('attachmentBasePath.selectDir'), fp.modeGetFolder);
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.appendFilters(fp.filterAll);
.createInstance(nsIFilePicker); if (await fp.show() != fp.returnOK) {
if (oldPathFile) {
fp.displayDirectory = oldPathFile;
}
fp.init(window, Zotero.getString('attachmentBasePath.selectDir'), nsIFilePicker.modeGetFolder);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() != nsIFilePicker.returnOK) {
return false; return false;
} }
var newPath = OS.Path.normalize(fp.file.path); var newPath = fp.file;
if (oldPath && oldPath == newPath) { if (oldPath && oldPath == newPath) {
Zotero.debug("Base directory hasn't changed"); Zotero.debug("Base directory hasn't changed");
@ -580,7 +576,7 @@ Zotero_Preferences.Attachment_Base_Directory = {
} }
return this.changePath(newPath); return this.changePath(newPath);
}), },
changePath: Zotero.Promise.coroutine(function* (basePath) { changePath: Zotero.Promise.coroutine(function* (basePath) {

View file

@ -25,6 +25,8 @@
"use strict"; "use strict";
import FilePicker from 'zotero/filePicker';
Zotero_Preferences.Cite = { Zotero_Preferences.Cite = {
wordPluginIDs: new Set([ wordPluginIDs: new Set([
'zoteroOpenOfficeIntegration@zotero.org', 'zoteroOpenOfficeIntegration@zotero.org',
@ -133,21 +135,27 @@ Zotero_Preferences.Cite = {
/** /**
* Adds a new style to the style pane * Adds a new style to the style pane
**/ **/
addStyle: function () { addStyle: async function () {
const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString("zotero.preferences.styles.addStyle"), fp.modeOpen);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString("zotero.preferences.styles.addStyle"), nsIFilePicker.modeOpen);
fp.appendFilter("CSL Style", "*.csl"); fp.appendFilter("CSL Style", "*.csl");
var rv = fp.show(); var rv = await fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { if (rv == fp.returnOK || rv == fp.returnReplace) {
Zotero.Styles.install({ file: fp.file }, fp.file.path, true) try {
.catch(function (e) { await Zotero.Styles.install(
{
file: Zotero.File.pathToFile(fp.file)
},
fp.file,
true
);
}
catch (e) {
(new Zotero.Exception.Alert("styles.install.unexpectedError", (new Zotero.Exception.Alert("styles.install.unexpectedError",
fp.file.path, "styles.install.title", e)).present() fp.file, "styles.install.title", e)).present()
}); }
} }
}, },

View file

@ -27,6 +27,7 @@
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/osfile.jsm"); Components.utils.import("resource://gre/modules/osfile.jsm");
import FilePicker from 'zotero/filePicker';
Zotero_Preferences.General = { Zotero_Preferences.General = {
init: function () { init: function () {
@ -51,28 +52,25 @@ Zotero_Preferences.General = {
// //
// File handlers // File handlers
// //
chooseFileHandler: function (type) { chooseFileHandler: async function (type) {
var pref = this._getFileHandlerPref(type); var pref = this._getFileHandlerPref(type);
var currentPath = Zotero.Prefs.get(pref); var currentPath = Zotero.Prefs.get(pref);
var nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker);
if (currentPath) { if (currentPath) {
fp.displayDirectory = Zotero.File.pathToFile(OS.Path.dirname(currentPath)); fp.displayDirectory = OS.Path.dirname(currentPath);
} }
fp.init( fp.init(
window, window,
Zotero.getString('zotero.preferences.chooseApplication'), Zotero.getString('zotero.preferences.chooseApplication'),
nsIFilePicker.modeOpen fp.modeOpen
); );
fp.appendFilters(nsIFilePicker.filterApps); fp.appendFilters(fp.filterApps);
if (fp.show() != nsIFilePicker.returnOK) { if (await fp.show() != fp.returnOK) {
this._updateFileHandlerUI(); this._updateFileHandlerUI();
return false; return false;
} }
var newPath = OS.Path.normalize(fp.file.path); this.setFileHandler(type, fp.file);
this.setFileHandler(type, newPath);
}, },
setFileHandler: function (type, handler) { setFileHandler: function (type, handler) {

View file

@ -26,8 +26,9 @@
/** /**
* @fileOverview Tools for automatically retrieving a citation for the given PDF * @fileOverview Tools for automatically retrieving a citation for the given PDF
*/ */
import FilePicker from 'zotero/filePicker';
/** /**
* Front end for recognizing PDFs * Front end for recognizing PDFs
* @namespace * @namespace
@ -73,19 +74,17 @@ var Zotero_RTFScan = new function() {
/** /**
* Called to select the file to be processed * Called to select the file to be processed
*/ */
this.chooseInputFile = function() { this.chooseInputFile = async function () {
// display file picker // display file picker
const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString("rtfScan.openTitle"), fp.modeOpen);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString("rtfScan.openTitle"), nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterAll); fp.appendFilters(fp.filterAll);
fp.appendFilter(Zotero.getString("rtfScan.rtf"), "*.rtf"); fp.appendFilter(Zotero.getString("rtfScan.rtf"), "*.rtf");
var rv = fp.show(); var rv = await fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { if (rv == fp.returnOK || rv == fp.returnReplace) {
inputFile = fp.file; inputFile = Zotero.File.pathToFile(fp.file);
_updatePath(); _updatePath();
} }
} }
@ -93,11 +92,9 @@ var Zotero_RTFScan = new function() {
/** /**
* Called to select the output file * Called to select the output file
*/ */
this.chooseOutputFile = function() { this.chooseOutputFile = async function () {
const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString("rtfScan.saveTitle"), fp.modeSave);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString("rtfScan.saveTitle"), nsIFilePicker.modeSave);
fp.appendFilter(Zotero.getString("rtfScan.rtf"), "*.rtf"); fp.appendFilter(Zotero.getString("rtfScan.rtf"), "*.rtf");
if(inputFile) { if(inputFile) {
var leafName = inputFile.leafName; var leafName = inputFile.leafName;
@ -110,9 +107,9 @@ var Zotero_RTFScan = new function() {
fp.defaultString = "Untitled.rtf"; fp.defaultString = "Untitled.rtf";
} }
var rv = fp.show(); var rv = await fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { if (rv == fp.returnOK || rv == fp.returnReplace) {
outputFile = fp.file; outputFile = Zotero.File.pathToFile(fp.file);
_updatePath(); _updatePath();
} }
} }

View file

@ -7,12 +7,14 @@
<p id="result"></p> <p id="result"></p>
<script src="../include.js"></script> <script src="../include.js"></script>
<script type="text/javascript"> <script type="text/javascript">
Zotero.Promise.coroutine(function* (){ import FilePicker from 'zotero/filePicker';
(async function () {
// Create schema // Create schema
var schema = {"itemTypes":{}, "creatorTypes":{}, "fields":{}}; var schema = {"itemTypes":{}, "creatorTypes":{}, "fields":{}};
var types = Zotero.ItemTypes.getTypes(); var types = Zotero.ItemTypes.getTypes();
var fieldIDs = yield Zotero.DB.columnQueryAsync("SELECT fieldID FROM fieldsCombined"); var fieldIDs = await Zotero.DB.columnQueryAsync("SELECT fieldID FROM fieldsCombined");
var baseMappedFields = Zotero.ItemFields.getBaseMappedFields(); var baseMappedFields = Zotero.ItemFields.getBaseMappedFields();
for (let fieldID of fieldIDs) { for (let fieldID of fieldIDs) {
@ -70,19 +72,20 @@
} }
// Write to file // Write to file
var nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString('dataDir.selectDir'), fp.modeGetFolder);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString('dataDir.selectDir'), nsIFilePicker.modeGetFolder);
let resultElem = document.getElementById('result'); let resultElem = document.getElementById('result');
if (fp.show() != nsIFilePicker.returnOK) { if (await fp.show() != fp.returnOK) {
result.innerHTML = '<p>Failed.</p>'; result.innerHTML = '<p>Failed.</p>';
} else { } else {
let schemaFile = fp.file; let schemaFile = fp.file;
schemaFile.append("connectorTypeSchemaData.js"); schemaFile.append("connectorTypeSchemaData.js");
Zotero.File.putContents(schemaFile, `Zotero.Connector_Types.schema = ${JSON.stringify(schema)}`); await Zotero.File.putContentsAsync(
result.innerHTML = `<p>Wrote ${schemaFile.path} successfully.</p>`; schemaFile,
`Zotero.Connector_Types.schema = ${JSON.stringify(schema)}`
);
result.innerHTML = `<p>Wrote ${schemaFile} successfully.</p>`;
} }
})(); })();
</script> </script>

View file

@ -23,6 +23,8 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
*/ */
import FilePicker from 'zotero/filePicker';
var Zotero_CSL_Editor = new function() { var Zotero_CSL_Editor = new function() {
this.init = init; this.init = init;
this.handleKeyPress = handleKeyPress; this.handleKeyPress = handleKeyPress;
@ -83,13 +85,11 @@ var Zotero_CSL_Editor = new function() {
this.generateBibliography(this.loadStyleFromEditor()); this.generateBibliography(this.loadStyleFromEditor());
} }
this.save = function() { this.save = async function () {
var editor = document.getElementById('zotero-csl-editor'); var editor = document.getElementById('zotero-csl-editor');
var style = editor.value; var style = editor.value;
const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString('styles.editor.save'), fp.modeSave);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString('styles.editor.save'), nsIFilePicker.modeSave);
fp.appendFilter("Citation Style Language", "*.csl"); fp.appendFilter("Citation Style Language", "*.csl");
//get the filename from the id; we could consider doing even more here like creating the id from filename. //get the filename from the id; we could consider doing even more here like creating the id from filename.
var parser = new DOMParser(); var parser = new DOMParser();
@ -102,10 +102,10 @@ var Zotero_CSL_Editor = new function() {
else { else {
fp.defaultString = "untitled.csl"; fp.defaultString = "untitled.csl";
} }
var rv = fp.show(); var rv = await fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) { if (rv == fp.returnOK || rv == fp.returnReplace) {
var outputFile = fp.file; let outputFile = fp.file;
Zotero.File.putContents(outputFile, style); Zotero.File.putContentsAsync(outputFile, style);
} }
}; };

View file

@ -25,6 +25,8 @@
"use strict"; "use strict";
import FilePicker from 'zotero/filePicker';
Zotero.DataDirectory = { Zotero.DataDirectory = {
MIGRATION_MARKER: 'migrate-dir', MIGRATION_MARKER: 'migrate-dir',
@ -439,7 +441,7 @@ Zotero.DataDirectory = {
}, },
choose: Zotero.Promise.coroutine(function* (forceQuitNow, useHomeDir, moreInfoCallback) { choose: async function (forceQuitNow, useHomeDir, moreInfoCallback) {
var win = Services.wm.getMostRecentWindow('navigator:browser'); var win = Services.wm.getMostRecentWindow('navigator:browser');
var ps = Services.prompt; var ps = Services.prompt;
@ -450,17 +452,13 @@ Zotero.DataDirectory = {
} }
} }
else { else {
var nsIFilePicker = Components.interfaces.nsIFilePicker;
while (true) { while (true) {
var fp = Components.classes["@mozilla.org/filepicker;1"] let fp = new FilePicker();
.createInstance(nsIFilePicker); fp.init(win, Zotero.getString('dataDir.selectDir'), fp.modeGetFolder);
fp.init(win, Zotero.getString('dataDir.selectDir'), nsIFilePicker.modeGetFolder); fp.displayDirectory = this._dir ? this._dir : OS.Path.dirname(this.defaultDir);
fp.displayDirectory = Zotero.File.pathToFile( fp.appendFilters(fp.filterAll);
this._dir ? this._dir : OS.Path.dirname(this.defaultDir) if (await fp.show() == fp.returnOK) {
); let file = Zotero.File.pathToFile(fp.file);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) {
var file = fp.file;
let dialogText = ''; let dialogText = '';
let dialogTitle = ''; let dialogTitle = '';
@ -547,24 +545,22 @@ Zotero.DataDirectory = {
} }
return useHomeDir ? true : file; return useHomeDir ? true : file;
}), },
forceChange: function (win) { forceChange: async function (win) {
if (!win) { if (!win) {
win = Services.wm.getMostRecentWindow('navigator:browser'); win = Services.wm.getMostRecentWindow('navigator:browser');
} }
var ps = Services.prompt; var ps = Services.prompt;
var nsIFilePicker = Components.interfaces.nsIFilePicker;
while (true) { while (true) {
var fp = Components.classes["@mozilla.org/filepicker;1"] let fp = new FilePicker();
.createInstance(nsIFilePicker); fp.init(win, Zotero.getString('dataDir.selectNewDir', Zotero.clientName), fp.modeGetFolder);
fp.init(win, Zotero.getString('dataDir.selectNewDir', Zotero.clientName), nsIFilePicker.modeGetFolder); fp.displayDirectory = this.dir;
fp.displayDirectory = Zotero.File.pathToFile(this.dir); fp.appendFilters(fp.filterAll);
fp.appendFilters(nsIFilePicker.filterAll); if (await fp.show() == fp.returnOK) {
if (fp.show() == nsIFilePicker.returnOK) { let file = Zotero.File.pathToFile(fp.file);
var file = fp.file;
if (file.directoryEntries.hasMoreElements()) { if (file.directoryEntries.hasMoreElements()) {
ps.alert(null, ps.alert(null,

View file

@ -23,6 +23,8 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
*/ */
import FilePicker from 'zotero/filePicker';
/* /*
* This object contains the various functions for the interface * This object contains the various functions for the interface
*/ */
@ -955,16 +957,15 @@ var ZoteroPane = new function()
return collection.saveTx(); return collection.saveTx();
}); });
this.importFeedsFromOPML = Zotero.Promise.coroutine(function* (event) { this.importFeedsFromOPML = async function (event) {
var nsIFilePicker = Components.interfaces.nsIFilePicker;
while (true) { while (true) {
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); let fp = new FilePicker();
fp.init(window, Zotero.getString('fileInterface.importOPML'), nsIFilePicker.modeOpen); fp.init(window, Zotero.getString('fileInterface.importOPML'), fp.modeOpen);
fp.appendFilter(Zotero.getString('fileInterface.OPMLFeedFilter'), '*.opml; *.xml'); fp.appendFilter(Zotero.getString('fileInterface.OPMLFeedFilter'), '*.opml; *.xml');
fp.appendFilters(nsIFilePicker.filterAll); fp.appendFilters(fp.filterAll);
if (fp.show() == nsIFilePicker.returnOK) { if (await fp.show() == fp.returnOK) {
var contents = yield Zotero.File.getContentsAsync(fp.file.path); var contents = await Zotero.File.getContentsAsync(fp.file.path);
var success = yield Zotero.Feeds.importFromOPML(contents); var success = await Zotero.Feeds.importFromOPML(contents);
if (success) { if (success) {
return true; return true;
} }
@ -974,7 +975,7 @@ var ZoteroPane = new function()
return false; return false;
} }
} }
}); };
this.newFeedFromURL = Zotero.Promise.coroutine(function* () { this.newFeedFromURL = Zotero.Promise.coroutine(function* () {
@ -3579,7 +3580,7 @@ var ZoteroPane = new function()
}); });
this.addAttachmentFromDialog = Zotero.Promise.coroutine(function* (link, parentItemID) { this.addAttachmentFromDialog = async function (link, parentItemID) {
if (!this.canEdit()) { if (!this.canEdit()) {
this.displayCannotEditLibraryMessage(); this.displayCannotEditLibraryMessage();
return; return;
@ -3609,24 +3610,15 @@ var ZoteroPane = new function()
var libraryID = collectionTreeRow.ref.libraryID; var libraryID = collectionTreeRow.ref.libraryID;
var nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString('pane.item.attachments.select'), fp.modeOpenMultiple);
.createInstance(nsIFilePicker); fp.appendFilters(fp.filterAll);
fp.init(window, Zotero.getString('pane.item.attachments.select'), nsIFilePicker.modeOpenMultiple);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() != nsIFilePicker.returnOK) { if (await fp.show() != fp.returnOK) {
return; return;
} }
var enumerator = fp.files; var files = fp.files;
var files = [];
while (enumerator.hasMoreElements()) {
let file = enumerator.getNext();
file.QueryInterface(Components.interfaces.nsIFile);
files.push(file.path);
}
var addedItems = []; var addedItems = [];
var collection; var collection;
var fileBaseName; var fileBaseName;
@ -3637,7 +3629,7 @@ var ZoteroPane = new function()
if (files.length == 1 && Zotero.Attachments.shouldAutoRenameFile(link)) { if (files.length == 1 && Zotero.Attachments.shouldAutoRenameFile(link)) {
let parentItem = Zotero.Items.get(parentItemID); let parentItem = Zotero.Items.get(parentItemID);
if (!parentItem.numNonHTMLFileAttachments()) { if (!parentItem.numNonHTMLFileAttachments()) {
fileBaseName = yield Zotero.Attachments.getRenamedFileBaseNameIfAllowedType( fileBaseName = await Zotero.Attachments.getRenamedFileBaseNameIfAllowedType(
parentItem, files[0] parentItem, files[0]
); );
} }
@ -3656,7 +3648,7 @@ var ZoteroPane = new function()
try { try {
if (fileBaseName) { if (fileBaseName) {
let ext = Zotero.File.getExtension(file); let ext = Zotero.File.getExtension(file);
let newName = yield Zotero.File.rename( let newName = await Zotero.File.rename(
file, file,
fileBaseName + (ext ? '.' + ext : ''), fileBaseName + (ext ? '.' + ext : ''),
{ {
@ -3671,7 +3663,7 @@ var ZoteroPane = new function()
Zotero.logError(e); Zotero.logError(e);
} }
item = yield Zotero.Attachments.linkFromFile({ item = await Zotero.Attachments.linkFromFile({
file, file,
parentItemID, parentItemID,
collections: collection ? [collection] : undefined collections: collection ? [collection] : undefined
@ -3684,7 +3676,7 @@ var ZoteroPane = new function()
continue; continue;
} }
item = yield Zotero.Attachments.importFromFile({ item = await Zotero.Attachments.importFromFile({
file, file,
libraryID, libraryID,
fileBaseName, fileBaseName,
@ -3700,7 +3692,7 @@ var ZoteroPane = new function()
if (!parentItemID) { if (!parentItemID) {
Zotero.RecognizePDF.autoRecognizeItems(addedItems); Zotero.RecognizePDF.autoRecognizeItems(addedItems);
} }
}); };
this.findPDFForSelectedItems = async function () { this.findPDFForSelectedItems = async function () {
@ -4643,7 +4635,7 @@ var ZoteroPane = new function()
}; };
this.relinkAttachment = Zotero.Promise.coroutine(function* (itemID) { this.relinkAttachment = async function (itemID) {
if (!this.canEdit()) { if (!this.canEdit()) {
this.displayCannotEditLibraryMessage(); this.displayCannotEditLibraryMessage();
return; return;
@ -4655,10 +4647,8 @@ var ZoteroPane = new function()
} }
while (true) { while (true) {
var nsIFilePicker = Components.interfaces.nsIFilePicker; let fp = new FilePicker();
var fp = Components.classes["@mozilla.org/filepicker;1"] fp.init(window, Zotero.getString('pane.item.attachments.select'), fp.modeOpen);
.createInstance(nsIFilePicker);
fp.init(window, Zotero.getString('pane.item.attachments.select'), nsIFilePicker.modeOpen);
var file = item.getFilePath(); var file = item.getFilePath();
if (!file) { if (!file) {
@ -4666,16 +4656,15 @@ var ZoteroPane = new function()
break; break;
} }
var dir = yield Zotero.File.getClosestDirectory(file); var dir = await Zotero.File.getClosestDirectory(file);
if (dir) { if (dir) {
fp.displayDirectory = Zotero.File.pathToFile(dir); fp.displayDirectory = dir;
} }
fp.appendFilters(Components.interfaces.nsIFilePicker.filterAll); fp.appendFilters(fp.filterAll);
if (fp.show() == nsIFilePicker.returnOK) { if (await fp.show() == fp.returnOK) {
let file = fp.file; let file = Zotero.File.pathToFile(fp.file);
file.QueryInterface(Components.interfaces.nsILocalFile);
// Disallow hidden files // Disallow hidden files
// TODO: Display a message // TODO: Display a message
@ -4689,13 +4678,13 @@ var ZoteroPane = new function()
continue; continue;
} }
yield item.relinkAttachmentFile(file.path); await item.relinkAttachmentFile(file.path);
break; break;
} }
break; break;
} }
}); };
this.updateReadLabel = function () { this.updateReadLabel = function () {

View file

@ -80,7 +80,7 @@ describe("Zotero.Sync.Data.Local", function() {
// extra1 functionality not used at the moment // extra1 functionality not used at the moment
it.skip("should prompt for data reset and allow to choose a new data directory", function* (){ it.skip("should prompt for data reset and allow to choose a new data directory", function* (){
sinon.stub(Zotero.DataDirectory, 'forceChange').returns(true); sinon.stub(Zotero.DataDirectory, 'forceChange').returns(Zotero.Promise.resolve(true));
yield Zotero.Users.setCurrentUserID(1); yield Zotero.Users.setCurrentUserID(1);
yield Zotero.Users.setCurrentUsername("A"); yield Zotero.Users.setCurrentUsername("A");