diff --git a/src/renderer/src/stories/FileSystemSelector.js b/src/renderer/src/stories/FileSystemSelector.js index 81967a6ad..df79bc57f 100644 --- a/src/renderer/src/stories/FileSystemSelector.js +++ b/src/renderer/src/stories/FileSystemSelector.js @@ -3,6 +3,22 @@ import { LitElement, css, html } from "lit"; import { remote } from "../electron/index"; const { dialog } = remote; +function getObjectTypeReferenceString(type, multiple, { nested, native } = {}) { + if (Array.isArray(type)) + return `${multiple ? "" : "a "}${type + .map((type) => getObjectTypeReferenceString(type, multiple, { native, nested: true })) + .join(" / ")}`; + + const isDir = type === "directory"; + return multiple && (!isDir || (isDir && !native)) + ? type === "directory" + ? "directories" + : "files" + : nested + ? type + : `a ${type}`; +} + const componentCSS = css` * { box-sizing: border-box; @@ -13,6 +29,16 @@ const componentCSS = css` width: 100%; } + :host([manytypes="true"]) > button { + cursor: default; + } + + #button-div { + margin-top: 10px; + display: flex; + gap: 5px; + } + button { background: WhiteSmoke; border: 1px solid #c3c3c3; @@ -130,9 +156,27 @@ export class FilesystemSelector extends LitElement { this.dispatchEvent(event); }; + async selectFormat(type = this.type) { + if (dialog) { + const file = await this.#useElectronDialog(type); + const path = file.filePath ?? file.filePaths?.[0]; + this.#handleFiles(path); + } else { + let handles = await (type === "directory" + ? window.showDirectoryPicker() + : window.showOpenFilePicker({ multiple: this.multiple }) + ).catch((e) => this.#onCancel()); // Call using the same options + + const result = Array.isArray(handles) ? handles.map((o) => o.name) : handles.name; + this.#handleFiles(result); + } + } + render() { let resolved, isUpdated; + const isMultipleTypes = Array.isArray(this.type); + this.setAttribute("manytypes", isMultipleTypes); const isArray = Array.isArray(this.value); const len = isArray ? this.value.length : 0; @@ -156,29 +200,12 @@ export class FilesystemSelector extends LitElement { : this.value[0] : this.value; - const objectTypeReference = this.multiple - ? this.type === "directory" - ? "directories" - : "files" - : `a ${this.type}`; + const objectTypeReference = getObjectTypeReferenceString(this.type, this.multiple); return html` + ${isMultipleTypes + ? html`
+ ${this.type.map( + (type) => + html` this.selectFormat(type)} + >Select + ${getObjectTypeReferenceString(type, this.multiple, { native: true })}` + )} +
` + : ""} `; } } diff --git a/src/renderer/src/stories/FileSystemSelector.stories.js b/src/renderer/src/stories/FileSystemSelector.stories.js index 035d61938..75ba900eb 100644 --- a/src/renderer/src/stories/FileSystemSelector.stories.js +++ b/src/renderer/src/stories/FileSystemSelector.stories.js @@ -6,10 +6,12 @@ export default { const Template = (args) => new FilesystemSelector(args); +const types = ["file", "directory"]; + export const File = Template.bind({}); export const Folder = Template.bind({}); Folder.args = { - type: "directory", + type: types[1], }; export const FileMultiple = Template.bind({}); @@ -17,6 +19,17 @@ FileMultiple.args = { multiple: true }; export const FolderMultiple = Template.bind({}); FolderMultiple.args = { - type: "directory", + type: types[1], + multiple: true, +}; + +export const Both = Template.bind({}); +Both.args = { + type: types, +}; + +export const BothMultiple = Template.bind({}); +BothMultiple.args = { + type: types, multiple: true, }; diff --git a/src/renderer/src/stories/JSONSchemaInput.js b/src/renderer/src/stories/JSONSchemaInput.js index 6918014bb..5fee127a5 100644 --- a/src/renderer/src/stories/JSONSchemaInput.js +++ b/src/renderer/src/stories/JSONSchemaInput.js @@ -12,6 +12,8 @@ import { Modal } from "./Modal"; import { capitalize } from "./forms/utils"; const isFilesystemSelector = (format) => { + if (Array.isArray(format)) return format.map(isFilesystemSelector).every(Boolean) ? format : null; + const matched = name.match(/(.+_)?(.+)_paths?/); if (!format && matched) format = matched[2] === "folder" ? "directory" : matched[2]; return ["file", "directory"].includes(format) ? format : null; // Handle file and directory formats