diff --git a/package.json b/package.json index af31679..1e7153d 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,8 @@ }, "jupyterlab": { "extension": true, - "outputDir": "jupyterlab-filesystem-access/labextension" + "outputDir": "jupyterlab-filesystem-access/labextension", + "schemaDir": "schema" }, "eslintConfig": { "extends": [ diff --git a/schema/plugin.json b/schema/plugin.json new file mode 100644 index 0000000..396dd60 --- /dev/null +++ b/schema/plugin.json @@ -0,0 +1,69 @@ +{ + "title": "File System Access Widget", + "description": "File Browser widget settings.", + "jupyter.lab.toolbars": { + "FileSystemAccess": [{ "name": "open-folder", "rank": 0 }] + }, + "jupyter.lab.transform": true, + "properties": { + "toolbar": { + "title": "File System Access browser toolbar items", + "description": "Note: To disable a toolbar item,\ncopy it to User Preferences and add the\n\"disabled\" key. The following example will disable the uploader button:\n{\n \"toolbar\": [\n {\n \"name\": \"uploader\",\n \"disabled\": true\n }\n ]\n}\n\nToolbar description:", + "items": { + "$ref": "#/definitions/toolbarItem" + }, + "type": "array", + "default": [] + } + }, + "additionalProperties": false, + "type": "object", + "definitions": { + "toolbarItem": { + "properties": { + "name": { + "title": "Unique name", + "type": "string" + }, + "args": { + "title": "Command arguments", + "type": "object" + }, + "command": { + "title": "Command id", + "type": "string", + "default": "" + }, + "disabled": { + "title": "Whether the item is ignored or not", + "type": "boolean", + "default": false + }, + "icon": { + "title": "Item icon id", + "description": "If defined, it will override the command icon", + "type": "string" + }, + "label": { + "title": "Item label", + "description": "If defined, it will override the command label", + "type": "string" + }, + "type": { + "title": "Item type", + "type": "string", + "enum": ["command", "spacer"] + }, + "rank": { + "title": "Item rank", + "type": "number", + "minimum": 0, + "default": 50 + } + }, + "required": ["name"], + "additionalProperties": false, + "type": "object" + } + } +} diff --git a/src/index.ts b/src/index.ts index 3264376..8d217c3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,29 +3,45 @@ import { JupyterFrontEndPlugin } from '@jupyterlab/application'; -import { ToolbarButton } from '@jupyterlab/apputils'; +import { + createToolbarFactory, + setToolbar, + IToolbarWidgetRegistry, + ToolbarButton +} from '@jupyterlab/apputils'; + +import { IFileBrowserFactory, FileBrowser } from '@jupyterlab/filebrowser'; -import { IFileBrowserFactory } from '@jupyterlab/filebrowser'; +import { ISettingRegistry } from '@jupyterlab/settingregistry'; -import { ITranslator } from '@jupyterlab/translation'; +import { ITranslator, nullTranslator } from '@jupyterlab/translation'; import { listIcon, folderIcon } from '@jupyterlab/ui-components'; import { FileSystemDrive } from './drive'; +/** + * The file browser factory + */ +const FILE_BROWSER_FACTORY = 'FileSystemAccess'; + /** * Initialization data for the jupyterlab-filesystem-access extension. */ const plugin: JupyterFrontEndPlugin = { id: 'jupyterlab-filesystem-access:plugin', requires: [IFileBrowserFactory, ITranslator], + optional: [ISettingRegistry, IToolbarWidgetRegistry], autoStart: true, activate: ( app: JupyterFrontEnd, browser: IFileBrowserFactory, - translator: ITranslator + translator: ITranslator, + settingRegistry: ISettingRegistry | null, + toolbarRegistry: IToolbarWidgetRegistry | null ) => { - if (!window.showDirectoryPicker) { + const showDirectoryPicker = window.showDirectoryPicker; + if (!showDirectoryPicker) { // bail if the browser does not support the File System API console.warn( 'The File System Access API is not supported in this browser.' @@ -49,24 +65,47 @@ const plugin: JupyterFrontEndPlugin = { widget.title.caption = trans.__('Local File System'); widget.title.icon = listIcon; - const openDirectoryButton = new ToolbarButton({ - icon: folderIcon, - onClick: async () => { - const directoryHandle = await window.showDirectoryPicker(); - - if (directoryHandle) { - drive.rootHandle = directoryHandle; + const toolbar = widget.toolbar; + toolbar.id = 'jp-filesystem-toolbar'; + + if (toolbarRegistry && settingRegistry) { + // Set toolbar + setToolbar( + toolbar, + createToolbarFactory( + toolbarRegistry, + settingRegistry, + FILE_BROWSER_FACTORY, + plugin.id, + translator ?? nullTranslator + ), + toolbar + ); - // Go to root directory - widget.model.cd('/'); + toolbarRegistry.addFactory( + FILE_BROWSER_FACTORY, + 'open-folder', + (browser: FileBrowser) => { + const openDirectoryButton = new ToolbarButton({ + icon: folderIcon, + onClick: async () => { + const directoryHandle = await showDirectoryPicker(); + + if (directoryHandle) { + drive.rootHandle = directoryHandle; + + // Go to root directory + widget.model.cd('/'); + } + }, + tooltip: trans.__('Open a new folder') + }); + return openDirectoryButton; } - }, - tooltip: trans.__('Open a new folder') - }); - - widget.toolbar.insertItem(0, 'open-directory', openDirectoryButton); + ); + } - app.shell.add(widget, 'left'); + app.shell.add(widget, 'left', { type: 'FileSystemAccess' }); } };