{"version":3,"mappings":"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","names":["e","s","t","FilesRegistry","TypedEventTarget","getRegistry","scopedGlobals","registerFileListHeader","header","validateHeader","logger","NewMenuEntryCategory","NewMenu","entry","entryIndex","context","id","getNewFileMenu","addNewFileMenuEntry","TextSvg","addMenuRichWorkspace","descriptionFile","loadState","Permission","content","node","showError","source","response","axios","fileid","file","File","getCurrentUser","showSuccess","emit","FilesHeaderRichWorkspaceView","FilesHeaderRichWorkspaceInstance","latestFolder","enabled","_","view","FilesWorkspaceHeader","el","folder","__vitePreload","hasRichWorkspace","path","Vue","workspaceAvailable","registerDavProperty"],"ignoreList":[0,1,2],"sources":["../node_modules/typescript-event-target/dist/index.mjs","../node_modules/@nextcloud/files/dist/index.mjs","../node_modules/@mdi/svg/svg/text.svg?raw","../src/helpers/files.js","../src/init.js"],"sourcesContent":["var e=class extends EventTarget{dispatchTypedEvent(s,t){return super.dispatchEvent(t)}};export{e as TypedEventTarget};\n","import { s as scopedGlobals, l as logger, F as FileType } from \"./chunks/folder-29HuacU_.mjs\";\nimport { a, b, N, c, P } from \"./chunks/folder-29HuacU_.mjs\";\nimport { TypedEventTarget } from \"typescript-event-target\";\nimport isSvg from \"is-svg\";\nimport { getCapabilities } from \"@nextcloud/capabilities\";\nimport { extname, basename } from \"@nextcloud/paths\";\nimport { getCanonicalLocale, getLanguage } from \"@nextcloud/l10n\";\nclass FilesRegistry extends TypedEventTarget {\n}\nfunction getRegistry() {\n scopedGlobals.registry ??= new FilesRegistry();\n return scopedGlobals.registry;\n}\nfunction getFilesRegistry() {\n return getRegistry();\n}\nconst DefaultType = Object.freeze({\n DEFAULT: \"default\",\n HIDDEN: \"hidden\"\n});\nfunction registerFileAction(action) {\n validateAction$1(action);\n scopedGlobals.fileActions ??= /* @__PURE__ */ new Map();\n if (scopedGlobals.fileActions.has(action.id)) {\n logger.error(`FileAction ${action.id} already registered`, { action });\n return;\n }\n scopedGlobals.fileActions.set(action.id, action);\n getRegistry().dispatchTypedEvent(\"register:action\", new CustomEvent(\"register:action\", { detail: action }));\n}\nfunction getFileActions() {\n if (scopedGlobals.fileActions) {\n return [...scopedGlobals.fileActions.values()];\n }\n return [];\n}\nfunction validateAction$1(action) {\n if (!action.id || typeof action.id !== \"string\") {\n throw new Error(\"Invalid id\");\n }\n if (!action.displayName || typeof action.displayName !== \"function\") {\n throw new Error(\"Invalid displayName function\");\n }\n if (\"title\" in action && typeof action.title !== \"function\") {\n throw new Error(\"Invalid title function\");\n }\n if (!action.iconSvgInline || typeof action.iconSvgInline !== \"function\") {\n throw new Error(\"Invalid iconSvgInline function\");\n }\n if (!action.exec || typeof action.exec !== \"function\") {\n throw new Error(\"Invalid exec function\");\n }\n if (\"enabled\" in action && typeof action.enabled !== \"function\") {\n throw new Error(\"Invalid enabled function\");\n }\n if (\"execBatch\" in action && typeof action.execBatch !== \"function\") {\n throw new Error(\"Invalid execBatch function\");\n }\n if (\"order\" in action && typeof action.order !== \"number\") {\n throw new Error(\"Invalid order\");\n }\n if (action.destructive !== void 0 && typeof action.destructive !== \"boolean\") {\n throw new Error(\"Invalid destructive flag\");\n }\n if (\"parent\" in action && typeof action.parent !== \"string\") {\n throw new Error(\"Invalid parent\");\n }\n if (action.default && !Object.values(DefaultType).includes(action.default)) {\n throw new Error(\"Invalid default\");\n }\n if (\"inline\" in action && typeof action.inline !== \"function\") {\n throw new Error(\"Invalid inline function\");\n }\n if (\"renderInline\" in action && typeof action.renderInline !== \"function\") {\n throw new Error(\"Invalid renderInline function\");\n }\n if (\"hotkey\" in action && action.hotkey !== void 0) {\n if (typeof action.hotkey !== \"object\") {\n throw new Error(\"Invalid hotkey configuration\");\n }\n if (typeof action.hotkey.key !== \"string\" || !action.hotkey.key) {\n throw new Error(\"Missing or invalid hotkey key\");\n }\n if (typeof action.hotkey.description !== \"string\" || !action.hotkey.description) {\n throw new Error(\"Missing or invalid hotkey description\");\n }\n }\n}\nfunction registerFileListAction(action) {\n validateAction(action);\n scopedGlobals.fileListActions ??= /* @__PURE__ */ new Map();\n if (scopedGlobals.fileListActions.has(action.id)) {\n logger.error(`FileListAction with id \"${action.id}\" is already registered`, { action });\n return;\n }\n scopedGlobals.fileListActions.set(action.id, action);\n getRegistry().dispatchTypedEvent(\"register:listAction\", new CustomEvent(\"register:listAction\", { detail: action }));\n}\nfunction getFileListActions() {\n if (scopedGlobals.fileListActions) {\n return [...scopedGlobals.fileListActions.values()];\n }\n return [];\n}\nfunction validateAction(action) {\n if (!action.id || typeof action.id !== \"string\") {\n throw new Error(\"Invalid id\");\n }\n if (!action.displayName || typeof action.displayName !== \"function\") {\n throw new Error(\"Invalid displayName function\");\n }\n if (\"iconSvgInline\" in action && typeof action.iconSvgInline !== \"function\") {\n throw new Error(\"Invalid iconSvgInline function\");\n }\n if (\"order\" in action && typeof action.order !== \"number\") {\n throw new Error(\"Invalid order\");\n }\n if (\"enabled\" in action && typeof action.enabled !== \"function\") {\n throw new Error(\"Invalid enabled function\");\n }\n if (!action.exec || typeof action.exec !== \"function\") {\n throw new Error(\"Invalid exec function\");\n }\n}\n/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nfunction registerFileListFilter(filter) {\n scopedGlobals.fileListFilters ??= /* @__PURE__ */ new Map();\n if (scopedGlobals.fileListFilters.has(filter.id)) {\n throw new Error(`File list filter \"${filter.id}\" already registered`);\n }\n scopedGlobals.fileListFilters.set(filter.id, filter);\n getRegistry().dispatchTypedEvent(\"register:listFilter\", new CustomEvent(\"register:listFilter\", { detail: filter }));\n}\nfunction unregisterFileListFilter(filterId) {\n if (scopedGlobals.fileListFilters && scopedGlobals.fileListFilters.has(filterId)) {\n scopedGlobals.fileListFilters.delete(filterId);\n getRegistry().dispatchTypedEvent(\"unregister:listFilter\", new CustomEvent(\"unregister:listFilter\", { detail: filterId }));\n }\n}\nfunction getFileListFilters() {\n if (scopedGlobals.fileListFilters) {\n return [...scopedGlobals.fileListFilters.values()];\n }\n return [];\n}\n/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nclass FileListFilter extends TypedEventTarget {\n id;\n order;\n constructor(id, order = 100) {\n super();\n this.id = id;\n this.order = order;\n }\n filter(nodes) {\n throw new Error(\"Not implemented\");\n }\n updateChips(chips) {\n this.dispatchTypedEvent(\"update:chips\", new CustomEvent(\"update:chips\", { detail: chips }));\n }\n filterUpdated() {\n this.dispatchTypedEvent(\"update:filter\", new CustomEvent(\"update:filter\"));\n }\n}\nfunction registerFileListHeader(header) {\n validateHeader(header);\n scopedGlobals.fileListHeaders ??= /* @__PURE__ */ new Map();\n if (scopedGlobals.fileListHeaders.has(header.id)) {\n logger.error(`Header ${header.id} already registered`, { header });\n return;\n }\n scopedGlobals.fileListHeaders.set(header.id, header);\n getRegistry().dispatchTypedEvent(\"register:listHeader\", new CustomEvent(\"register:listHeader\", { detail: header }));\n}\nfunction getFileListHeaders() {\n if (!scopedGlobals.fileListHeaders) {\n return [];\n }\n return [...scopedGlobals.fileListHeaders.values()];\n}\nfunction validateHeader(header) {\n if (!header.id || !header.render || !header.updated) {\n throw new Error(\"Invalid header: id, render and updated are required\");\n }\n if (typeof header.id !== \"string\") {\n throw new Error(\"Invalid id property\");\n }\n if (header.enabled !== void 0 && typeof header.enabled !== \"function\") {\n throw new Error(\"Invalid enabled property\");\n }\n if (header.render && typeof header.render !== \"function\") {\n throw new Error(\"Invalid render property\");\n }\n if (header.updated && typeof header.updated !== \"function\") {\n throw new Error(\"Invalid updated property\");\n }\n}\nfunction checkOptionalProperty(obj, property, type) {\n if (typeof obj[property] !== \"undefined\") {\n if (type === \"array\") {\n if (!Array.isArray(obj[property])) {\n throw new Error(`View ${property} must be an array`);\n }\n } else if (typeof obj[property] !== type) {\n throw new Error(`View ${property} must be a ${type}`);\n } else if (type === \"object\" && (obj[property] === null || Array.isArray(obj[property]))) {\n throw new Error(`View ${property} must be an object`);\n }\n }\n}\nclass Column {\n _column;\n constructor(column) {\n validateColumn(column);\n this._column = column;\n }\n get id() {\n return this._column.id;\n }\n get title() {\n return this._column.title;\n }\n get render() {\n return this._column.render;\n }\n get sort() {\n return this._column.sort;\n }\n get summary() {\n return this._column.summary;\n }\n}\nfunction validateColumn(column) {\n if (typeof column !== \"object\" || column === null) {\n throw new Error(\"View column must be an object\");\n }\n if (!column.id || typeof column.id !== \"string\") {\n throw new Error(\"A column id is required\");\n }\n if (!column.title || typeof column.title !== \"string\") {\n throw new Error(\"A column title is required\");\n }\n if (!column.render || typeof column.render !== \"function\") {\n throw new Error(\"A render function is required\");\n }\n checkOptionalProperty(column, \"sort\", \"function\");\n checkOptionalProperty(column, \"summary\", \"function\");\n}\nclass View {\n _view;\n constructor(view) {\n validateView(view);\n this._view = view;\n }\n get id() {\n return this._view.id;\n }\n get name() {\n return this._view.name;\n }\n get caption() {\n return this._view.caption;\n }\n get emptyTitle() {\n return this._view.emptyTitle;\n }\n get emptyCaption() {\n return this._view.emptyCaption;\n }\n get getContents() {\n return this._view.getContents;\n }\n get hidden() {\n return this._view.hidden;\n }\n get icon() {\n return this._view.icon;\n }\n set icon(icon) {\n this._view.icon = icon;\n }\n get order() {\n return this._view.order;\n }\n set order(order) {\n this._view.order = order;\n }\n get params() {\n return this._view.params;\n }\n set params(params) {\n this._view.params = params;\n }\n get columns() {\n return this._view.columns;\n }\n get emptyView() {\n return this._view.emptyView;\n }\n get parent() {\n return this._view.parent;\n }\n get sticky() {\n return this._view.sticky;\n }\n get expanded() {\n return this._view.expanded;\n }\n set expanded(expanded) {\n this._view.expanded = expanded;\n }\n get defaultSortKey() {\n return this._view.defaultSortKey;\n }\n get loadChildViews() {\n return this._view.loadChildViews;\n }\n}\nfunction validateView(view) {\n if (!view.icon || typeof view.icon !== \"string\" || !isSvg(view.icon)) {\n throw new Error(\"View icon is required and must be a valid svg string\");\n }\n if (!view.id || typeof view.id !== \"string\") {\n throw new Error(\"View id is required and must be a string\");\n }\n if (!view.getContents || typeof view.getContents !== \"function\") {\n throw new Error(\"View getContents is required and must be a function\");\n }\n if (!view.name || typeof view.name !== \"string\") {\n throw new Error(\"View name is required and must be a string\");\n }\n checkOptionalProperty(view, \"caption\", \"string\");\n checkOptionalProperty(view, \"columns\", \"array\");\n checkOptionalProperty(view, \"defaultSortKey\", \"string\");\n checkOptionalProperty(view, \"emptyCaption\", \"string\");\n checkOptionalProperty(view, \"emptyTitle\", \"string\");\n checkOptionalProperty(view, \"emptyView\", \"function\");\n checkOptionalProperty(view, \"expanded\", \"boolean\");\n checkOptionalProperty(view, \"hidden\", \"boolean\");\n checkOptionalProperty(view, \"loadChildViews\", \"function\");\n checkOptionalProperty(view, \"order\", \"number\");\n checkOptionalProperty(view, \"params\", \"object\");\n checkOptionalProperty(view, \"parent\", \"string\");\n checkOptionalProperty(view, \"sticky\", \"boolean\");\n if (view.columns) {\n view.columns.forEach(validateColumn);\n const columnIds = view.columns.reduce((set, column) => set.add(column.id), /* @__PURE__ */ new Set());\n if (columnIds.size !== view.columns.length) {\n throw new Error(\"View columns must have unique ids\");\n }\n }\n}\nclass Navigation extends TypedEventTarget {\n _views = [];\n _currentView = null;\n /**\n * Register a new view on the navigation\n *\n * @param views The views to register\n * @throws {Error} if a view with the same id is already registered\n * @throws {Error} if the registered view is invalid\n */\n register(...views) {\n for (const view of views) {\n if (this._views.find((search) => search.id === view.id)) {\n throw new Error(`IView id ${view.id} is already registered`);\n }\n validateView(view);\n }\n this._views.push(...views);\n this.dispatchTypedEvent(\"update\", new CustomEvent(\"update\"));\n }\n /**\n * Remove a registered view\n *\n * @param id The id of the view to remove\n */\n remove(id) {\n const index = this._views.findIndex((view) => view.id === id);\n if (index !== -1) {\n this._views.splice(index, 1);\n this.dispatchTypedEvent(\"update\", new CustomEvent(\"update\"));\n }\n }\n /**\n * Set the currently active view\n *\n * @param id - The id of the view to set as active\n * @throws {Error} If no view with the given id was registered\n * @fires UpdateActiveViewEvent\n */\n setActive(id) {\n if (id === null) {\n this._currentView = null;\n } else {\n const view = this._views.find(({ id: viewId }) => viewId === id);\n if (!view) {\n throw new Error(`No view with ${id} registered`);\n }\n this._currentView = view;\n }\n const event = new CustomEvent(\"updateActive\", { detail: this._currentView });\n this.dispatchTypedEvent(\"updateActive\", event);\n }\n /**\n * The currently active files view\n */\n get active() {\n return this._currentView;\n }\n /**\n * All registered views\n */\n get views() {\n return this._views;\n }\n}\nfunction getNavigation() {\n scopedGlobals.navigation ??= new Navigation();\n return scopedGlobals.navigation;\n}\nconst NewMenuEntryCategory = Object.freeze({\n /**\n * For actions where the user is intended to upload from their device\n */\n UploadFromDevice: 0,\n /**\n * For actions that create new nodes on the server without uploading\n */\n CreateNew: 1,\n /**\n * For everything not matching the other categories\n */\n Other: 2\n});\nclass NewMenu {\n _entries = [];\n registerEntry(entry) {\n this.validateEntry(entry);\n entry.category = entry.category ?? NewMenuEntryCategory.CreateNew;\n this._entries.push(entry);\n }\n unregisterEntry(entry) {\n const entryIndex = typeof entry === \"string\" ? this.getEntryIndex(entry) : this.getEntryIndex(entry.id);\n if (entryIndex === -1) {\n logger.warn(\"Entry not found, nothing removed\", { entry, entries: this.getEntries() });\n return;\n }\n this._entries.splice(entryIndex, 1);\n }\n /**\n * Get the list of registered entries\n *\n * @param context - The creation context. Usually the current folder\n */\n getEntries(context) {\n if (context) {\n return this._entries.filter((entry) => typeof entry.enabled === \"function\" ? entry.enabled(context) : true);\n }\n return this._entries;\n }\n getEntryIndex(id) {\n return this._entries.findIndex((entry) => entry.id === id);\n }\n validateEntry(entry) {\n if (!entry.id || !entry.displayName || !entry.iconSvgInline || !entry.handler) {\n throw new Error(\"Invalid entry\");\n }\n if (typeof entry.id !== \"string\" || typeof entry.displayName !== \"string\") {\n throw new Error(\"Invalid id or displayName property\");\n }\n if (entry.iconSvgInline && typeof entry.iconSvgInline !== \"string\") {\n throw new Error(\"Invalid icon provided\");\n }\n if (entry.enabled !== void 0 && typeof entry.enabled !== \"function\") {\n throw new Error(\"Invalid enabled property\");\n }\n if (typeof entry.handler !== \"function\") {\n throw new Error(\"Invalid handler property\");\n }\n if (\"order\" in entry && typeof entry.order !== \"number\") {\n throw new Error(\"Invalid order property\");\n }\n if (this.getEntryIndex(entry.id) !== -1) {\n throw new Error(\"Duplicate entry\");\n }\n }\n}\nfunction getNewFileMenu() {\n scopedGlobals.newFileMenu ??= new NewMenu();\n return scopedGlobals.newFileMenu;\n}\nfunction addNewFileMenuEntry(entry) {\n const newFileMenu = getNewFileMenu();\n return newFileMenu.registerEntry(entry);\n}\nfunction removeNewFileMenuEntry(entry) {\n const newFileMenu = getNewFileMenu();\n return newFileMenu.unregisterEntry(entry);\n}\nfunction getNewFileMenuEntries(context) {\n const newFileMenu = getNewFileMenu();\n return newFileMenu.getEntries(context).sort((a2, b2) => {\n if (a2.order !== void 0 && b2.order !== void 0 && a2.order !== b2.order) {\n return a2.order - b2.order;\n }\n return a2.displayName.localeCompare(b2.displayName, void 0, { numeric: true, sensitivity: \"base\" });\n });\n}\nfunction registerSidebarAction(action) {\n validateSidebarAction(action);\n scopedGlobals.filesSidebarActions ??= /* @__PURE__ */ new Map();\n if (scopedGlobals.filesSidebarActions.has(action.id)) {\n logger.warn(`Sidebar action with id \"${action.id}\" already registered. Skipping.`);\n return;\n }\n scopedGlobals.filesSidebarActions.set(action.id, action);\n logger.debug(`New sidebar action with id \"${action.id}\" registered.`);\n}\nfunction getSidebarActions() {\n if (scopedGlobals.filesSidebarActions) {\n return [...scopedGlobals.filesSidebarActions.values()];\n }\n return [];\n}\nfunction validateSidebarAction(action) {\n if (typeof action !== \"object\") {\n throw new Error(\"Sidebar action is not an object\");\n }\n if (!action.id || typeof action.id !== \"string\" || action.id !== CSS.escape(action.id)) {\n throw new Error(\"Sidebar actions need to have an id conforming to the HTML id attribute specifications\");\n }\n if (!action.displayName || typeof action.displayName !== \"function\") {\n throw new Error(\"Sidebar actions need to have a displayName function\");\n }\n if (!action.iconSvgInline || typeof action.iconSvgInline !== \"function\") {\n throw new Error(\"Sidebar actions need to have a iconSvgInline function\");\n }\n if (!action.enabled || typeof action.enabled !== \"function\") {\n throw new Error(\"Sidebar actions need to have an enabled function\");\n }\n if (!action.onClick || typeof action.onClick !== \"function\") {\n throw new Error(\"Sidebar actions need to have an onClick function\");\n }\n}\nfunction registerSidebarTab(tab) {\n validateSidebarTab(tab);\n scopedGlobals.filesSidebarTabs ??= /* @__PURE__ */ new Map();\n if (scopedGlobals.filesSidebarTabs.has(tab.id)) {\n logger.warn(`Sidebar tab with id \"${tab.id}\" already registered. Skipping.`);\n return;\n }\n scopedGlobals.filesSidebarTabs.set(tab.id, tab);\n logger.debug(`New sidebar tab with id \"${tab.id}\" registered.`);\n}\nfunction getSidebarTabs() {\n if (scopedGlobals.filesSidebarTabs) {\n return [...scopedGlobals.filesSidebarTabs.values()];\n }\n return [];\n}\nfunction validateSidebarTab(tab) {\n if (typeof tab !== \"object\") {\n throw new Error(\"Sidebar tab is not an object\");\n }\n if (!tab.id || typeof tab.id !== \"string\" || tab.id !== CSS.escape(tab.id)) {\n throw new Error(\"Sidebar tabs need to have an id conforming to the HTML id attribute specifications\");\n }\n if (!tab.tagName || typeof tab.tagName !== \"string\") {\n throw new Error(\"Sidebar tabs need to have the tagName name set\");\n }\n if (!tab.tagName.match(/^[a-z][a-z0-9-_]+$/)) {\n throw new Error('Sidebar tab \"tagName\" is invalid');\n }\n if (!tab.displayName || typeof tab.displayName !== \"string\") {\n throw new Error(\"Sidebar tabs need to have a name set\");\n }\n if (typeof tab.iconSvgInline !== \"string\" || !isSvg(tab.iconSvgInline)) {\n throw new Error(\"Sidebar tabs need to have an valid SVG icon\");\n }\n if (typeof tab.order !== \"number\") {\n throw new Error(\"Sidebar tabs need to have a numeric order set\");\n }\n if (tab.enabled && typeof tab.enabled !== \"function\") {\n throw new Error('Sidebar tab \"enabled\" is not a function');\n }\n if (tab.onInit && typeof tab.onInit !== \"function\") {\n throw new Error('Sidebar tab \"onInit\" is not a function');\n }\n}\nclass SidebarProxy {\n get #impl() {\n return window.OCA?.Files?._sidebar?.();\n }\n get available() {\n return !!this.#impl;\n }\n get isOpen() {\n return this.#impl?.isOpen ?? false;\n }\n get activeTab() {\n return this.#impl?.activeTab;\n }\n get node() {\n return this.#impl?.node;\n }\n open(node, tab) {\n this.#impl?.open(node, tab);\n }\n close() {\n this.#impl?.close();\n }\n setActiveTab(tabId) {\n this.#impl?.setActiveTab(tabId);\n }\n registerTab(tab) {\n registerSidebarTab(tab);\n }\n getTabs(context) {\n return this.#impl?.getTabs(context) ?? [];\n }\n getActions(context) {\n return this.#impl?.getActions(context) ?? [];\n }\n registerAction(action) {\n registerSidebarAction(action);\n }\n}\nfunction getSidebar() {\n return new SidebarProxy();\n}\nconst InvalidFilenameErrorReason = Object.freeze({\n ReservedName: \"reserved name\",\n Character: \"character\",\n Extension: \"extension\"\n});\nclass InvalidFilenameError extends Error {\n constructor(options) {\n super(`Invalid ${options.reason} '${options.segment}' in filename '${options.filename}'`, { cause: options });\n }\n /**\n * The filename that was validated\n */\n get filename() {\n return this.cause.filename;\n }\n /**\n * Reason why the validation failed\n */\n get reason() {\n return this.cause.reason;\n }\n /**\n * Part of the filename that caused this error\n */\n get segment() {\n return this.cause.segment;\n }\n}\nfunction validateFilename(filename) {\n const capabilities = getCapabilities().files;\n const forbiddenCharacters = capabilities.forbidden_filename_characters ?? [\"/\", \"\\\\\"];\n for (const character of forbiddenCharacters) {\n if (filename.includes(character)) {\n throw new InvalidFilenameError({ segment: character, reason: InvalidFilenameErrorReason.Character, filename });\n }\n }\n filename = filename.toLocaleLowerCase();\n const forbiddenFilenames = capabilities.forbidden_filenames ?? [\".htaccess\"];\n if (forbiddenFilenames.includes(filename)) {\n throw new InvalidFilenameError({ filename, segment: filename, reason: InvalidFilenameErrorReason.ReservedName });\n }\n const endOfBasename = filename.indexOf(\".\", 1);\n const basename2 = filename.substring(0, endOfBasename === -1 ? void 0 : endOfBasename);\n const forbiddenFilenameBasenames = capabilities.forbidden_filename_basenames ?? [];\n if (forbiddenFilenameBasenames.includes(basename2)) {\n throw new InvalidFilenameError({ filename, segment: basename2, reason: InvalidFilenameErrorReason.ReservedName });\n }\n const forbiddenFilenameExtensions = capabilities.forbidden_filename_extensions ?? [];\n for (const extension of forbiddenFilenameExtensions) {\n if (filename.length > extension.length && filename.endsWith(extension)) {\n throw new InvalidFilenameError({ segment: extension, reason: InvalidFilenameErrorReason.Extension, filename });\n }\n }\n}\nfunction isFilenameValid(filename) {\n try {\n validateFilename(filename);\n return true;\n } catch (error) {\n if (error instanceof InvalidFilenameError) {\n return false;\n }\n throw error;\n }\n}\nfunction getUniqueName(name, otherNames, options) {\n const opts = {\n suffix: (n) => `(${n})`,\n ignoreFileExtension: false,\n ...options\n };\n let newName = name;\n let i = 1;\n while (otherNames.includes(newName)) {\n const ext = opts.ignoreFileExtension ? \"\" : extname(name);\n const base = basename(name, ext);\n newName = `${base} ${opts.suffix(i++)}${ext}`;\n }\n return newName;\n}\nconst humanList = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\nconst humanListBinary = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\"];\nfunction formatFileSize(size, skipSmallSizes = false, binaryPrefixes = false, base1000 = false) {\n binaryPrefixes = binaryPrefixes && !base1000;\n if (typeof size === \"string\") {\n size = Number(size);\n }\n let order = size > 0 ? Math.floor(Math.log(size) / Math.log(base1000 ? 1e3 : 1024)) : 0;\n order = Math.min((binaryPrefixes ? humanListBinary.length : humanList.length) - 1, order);\n const readableFormat = binaryPrefixes ? humanListBinary[order] : humanList[order];\n let relativeSize = (size / Math.pow(base1000 ? 1e3 : 1024, order)).toFixed(1);\n if (skipSmallSizes === true && order === 0) {\n return (relativeSize !== \"0.0\" ? \"< 1 \" : \"0 \") + (binaryPrefixes ? humanListBinary[1] : humanList[1]);\n }\n if (order < 2) {\n relativeSize = parseFloat(relativeSize).toFixed(0);\n } else {\n relativeSize = parseFloat(relativeSize).toLocaleString(getCanonicalLocale());\n }\n return relativeSize + \" \" + readableFormat;\n}\nfunction parseFileSize(value, forceBinary = false) {\n try {\n value = `${value}`.toLocaleLowerCase().replaceAll(/\\s+/g, \"\").replaceAll(\",\", \".\");\n } catch {\n return null;\n }\n const match = value.match(/^([0-9]*(\\.[0-9]*)?)([kmgtp]?)(i?)b?$/);\n if (match === null || match[1] === \".\" || match[1] === \"\") {\n return null;\n }\n const bytesArray = {\n \"\": 0,\n k: 1,\n m: 2,\n g: 3,\n t: 4,\n p: 5,\n e: 6\n };\n const decimalString = `${match[1]}`;\n const base = match[4] === \"i\" || forceBinary ? 1024 : 1e3;\n return Math.round(Number.parseFloat(decimalString) * base ** bytesArray[match[3]]);\n}\nfunction stringify(value) {\n if (value instanceof Date) {\n return value.toISOString();\n }\n return String(value);\n}\nfunction orderBy(collection, identifiers, orders) {\n identifiers = identifiers ?? [(value) => value];\n orders = orders ?? [];\n const sorting = identifiers.map((_, index) => (orders[index] ?? \"asc\") === \"asc\" ? 1 : -1);\n const collator = Intl.Collator(\n [getLanguage(), getCanonicalLocale()],\n {\n // handle 10 as ten and not as one-zero\n numeric: true,\n usage: \"sort\"\n }\n );\n return [...collection].sort((a2, b2) => {\n for (const [index, identifier] of identifiers.entries()) {\n const value = collator.compare(stringify(identifier(a2)), stringify(identifier(b2)));\n if (value !== 0) {\n return value * sorting[index];\n }\n }\n return 0;\n });\n}\nconst FilesSortingMode = Object.freeze({\n Name: \"basename\",\n Modified: \"mtime\",\n Size: \"size\"\n});\nfunction sortNodes(nodes, options = {}) {\n const sortingOptions = {\n // Default to sort by name\n sortingMode: FilesSortingMode.Name,\n // Default to sort ascending\n sortingOrder: \"asc\",\n ...options\n };\n function basename2(node) {\n const name = node.displayname || node.attributes?.displayname || node.basename || \"\";\n if (node.type === FileType.Folder) {\n return name;\n }\n return name.lastIndexOf(\".\") > 0 ? name.slice(0, name.lastIndexOf(\".\")) : name;\n }\n const identifiers = [\n // 1: Sort favorites first if enabled\n ...sortingOptions.sortFavoritesFirst ? [(v) => v.attributes?.favorite !== 1] : [],\n // 2: Sort folders first if sorting by name\n ...sortingOptions.sortFoldersFirst ? [(v) => v.type !== \"folder\"] : [],\n // 3: Use sorting mode if NOT basename (to be able to use display name too)\n ...sortingOptions.sortingMode !== FilesSortingMode.Name ? [(v) => v[sortingOptions.sortingMode] ?? v.attributes[sortingOptions.sortingMode]] : [],\n // 4: Use display name if available, fallback to name\n (v) => basename2(v),\n // 5: Finally, use basename if all previous sorting methods failed\n (v) => v.basename\n ];\n const orders = [\n // (for 1): always sort favorites before normal files\n ...sortingOptions.sortFavoritesFirst ? [\"asc\"] : [],\n // (for 2): always sort folders before files\n ...sortingOptions.sortFoldersFirst ? [\"asc\"] : [],\n // (for 3): Reverse if sorting by mtime as mtime higher means edited more recent -> lower\n ...sortingOptions.sortingMode === FilesSortingMode.Modified ? [sortingOptions.sortingOrder === \"asc\" ? \"desc\" : \"asc\"] : [],\n // (also for 3 so make sure not to conflict with 2 and 3)\n ...sortingOptions.sortingMode !== FilesSortingMode.Modified && sortingOptions.sortingMode !== FilesSortingMode.Name ? [sortingOptions.sortingOrder] : [],\n // for 4: use configured sorting direction\n sortingOptions.sortingOrder,\n // for 5: use configured sorting direction\n sortingOptions.sortingOrder\n ];\n return orderBy(nodes, identifiers, orders);\n}\nexport {\n Column,\n DefaultType,\n a as File,\n FileListFilter,\n FileType,\n FilesSortingMode,\n b as Folder,\n InvalidFilenameError,\n InvalidFilenameErrorReason,\n Navigation,\n NewMenuEntryCategory,\n N as Node,\n c as NodeStatus,\n P as Permission,\n View,\n addNewFileMenuEntry,\n formatFileSize,\n getFileActions,\n getFileListActions,\n getFileListFilters,\n getFileListHeaders,\n getFilesRegistry,\n getNavigation,\n getNewFileMenu,\n getNewFileMenuEntries,\n getSidebar,\n getSidebarActions,\n getSidebarTabs,\n getUniqueName,\n isFilenameValid,\n orderBy,\n parseFileSize,\n registerFileAction,\n registerFileListAction,\n registerFileListFilter,\n registerFileListHeader,\n registerSidebarAction,\n registerSidebarTab,\n removeNewFileMenuEntry,\n sortNodes,\n unregisterFileListFilter,\n validateColumn,\n validateFilename,\n validateView\n};\n//# sourceMappingURL=index.mjs.map\n","export default \"\"","/**\n * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getCurrentUser } from '@nextcloud/auth'\nimport axios from '@nextcloud/axios'\nimport { showError, showSuccess } from '@nextcloud/dialogs'\nimport { emit } from '@nextcloud/event-bus'\nimport {\n\taddNewFileMenuEntry,\n\tFile,\n\tNewMenuEntryCategory,\n\tPermission,\n} from '@nextcloud/files'\nimport { loadState } from '@nextcloud/initial-state'\n\nimport TextSvg from '@mdi/svg/svg/text.svg?raw'\n\nimport { t } from '@nextcloud/l10n'\nimport Vue from 'vue'\n\nconst FILE_ACTION_IDENTIFIER = 'Edit with text app'\n\nexport const addMenuRichWorkspace = () => {\n\tconst descriptionFile =\n\t\t'Readme' + '.' + loadState('text', 'default_file_extension')\n\taddNewFileMenuEntry({\n\t\tid: 'rich-workspace-init',\n\t\tdisplayName: t('text', 'Add folder description'),\n\t\tcategory: NewMenuEntryCategory.Other,\n\t\tenabled(context) {\n\t\t\tif (!window?.OCA?.Text?.RichWorkspaceEnabled) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (Number(context.attributes['rich-workspace-file-flat'])) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Check read permission to not show option in file drop shares\n\t\t\treturn (\n\t\t\t\t(context.permissions & Permission.READ) !== 0\n\t\t\t\t&& (context.permissions & Permission.CREATE) !== 0\n\t\t\t)\n\t\t},\n\t\ticonSvgInline: TextSvg,\n\t\tasync handler(context, content) {\n\t\t\tconst contentNames = content.map((node) => node.basename)\n\n\t\t\tif (contentNames.includes(descriptionFile)) {\n\t\t\t\tshowError(\n\t\t\t\t\tt('text', '\"{name}\" already exist!', { name: descriptionFile }),\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst source =\n\t\t\t\tcontext.encodedSource + '/' + encodeURIComponent(descriptionFile)\n\t\t\tconst response = await axios({\n\t\t\t\tmethod: 'PUT',\n\t\t\t\turl: source,\n\t\t\t\theaders: {\n\t\t\t\t\tOverwrite: 'F',\n\t\t\t\t},\n\t\t\t})\n\t\t\tconst fileid = parseInt(response.headers['oc-fileid'])\n\t\t\tconst file = new File({\n\t\t\t\tsource: context.source + '/' + descriptionFile,\n\t\t\t\tid: fileid,\n\t\t\t\tmtime: new Date(),\n\t\t\t\tmime: 'text/markdown',\n\t\t\t\towner: getCurrentUser()?.uid || null,\n\t\t\t\tpermissions: Permission.ALL,\n\t\t\t\troot: context?.root || '/files/' + getCurrentUser()?.uid,\n\t\t\t})\n\n\t\t\tshowSuccess(t('text', 'Created \"{name}\"', { name: descriptionFile }))\n\n\t\t\tcontext.attributes['rich-workspace-file-flat'] = fileid\n\t\t\tcontext.attributes['rich-workspace-flat'] = ''\n\n\t\t\temit('files:node:created', file)\n\t\t\temit('files:node:updated', context)\n\t\t},\n\t})\n}\n\nlet FilesHeaderRichWorkspaceView\nlet FilesHeaderRichWorkspaceInstance\nlet latestFolder\n\nconst enabled = (_, view) => {\n\treturn ['files', 'favorites', 'public-share', 'personal'].includes(view.id)\n}\n\n/**\n * @type {import('@nexcloud/files').IFileListHeader}\n */\nexport const FilesWorkspaceHeader = {\n\tid: 'workspace',\n\torder: 10,\n\tenabled,\n\n\trender: async (el, folder) => {\n\t\tlatestFolder = folder\n\t\t// Import the RichWorkspace component only when needed\n\t\tif (!FilesHeaderRichWorkspaceView) {\n\t\t\tFilesHeaderRichWorkspaceView = (\n\t\t\t\tawait import('../views/RichWorkspace.vue')\n\t\t\t).default\n\t\t}\n\n\t\t// If an instance already exists, destroy it before creating a new one\n\t\tif (FilesHeaderRichWorkspaceInstance) {\n\t\t\tFilesHeaderRichWorkspaceInstance.$destroy()\n\t\t\tconsole.debug('Destroying existing FilesHeaderRichWorkspaceInstance')\n\t\t}\n\n\t\tconst hasRichWorkspace =\n\t\t\t!!latestFolder.attributes['rich-workspace-file-flat']\n\t\tconst content = latestFolder.attributes['rich-workspace-flat'] || ''\n\t\tconst path = latestFolder.path || ''\n\n\t\t// Create a new instance of the RichWorkspace component\n\t\tFilesHeaderRichWorkspaceInstance = new Vue({\n\t\t\textends: FilesHeaderRichWorkspaceView,\n\t\t\tpropsData: {\n\t\t\t\tcontent,\n\t\t\t\thasRichWorkspace,\n\t\t\t\tpath,\n\t\t\t},\n\t\t}).$mount(el)\n\n\t\twindow.FilesHeaderRichWorkspaceInstance = FilesHeaderRichWorkspaceInstance\n\t},\n\n\tupdated(folder, view) {\n\t\tlatestFolder = folder\n\t\tif (!FilesHeaderRichWorkspaceInstance) {\n\t\t\tconsole.error('No vue instance found for FilesWorkspaceHeader')\n\t\t\treturn\n\t\t}\n\n\t\tconst hasRichWorkspace =\n\t\t\t!!folder.attributes['rich-workspace-file-flat'] && enabled(folder, view)\n\t\tFilesHeaderRichWorkspaceInstance.hasRichWorkspace = hasRichWorkspace\n\t\tFilesHeaderRichWorkspaceInstance.content =\n\t\t\tfolder.attributes['rich-workspace-flat'] || ''\n\t\tFilesHeaderRichWorkspaceInstance.path = folder.path || ''\n\t},\n}\n\nexport { FILE_ACTION_IDENTIFIER }\n","/**\n * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { registerFileListHeader } from '@nextcloud/files'\nimport { registerDavProperty } from '@nextcloud/files/dav'\nimport { loadState } from '@nextcloud/initial-state'\nimport { addMenuRichWorkspace, FilesWorkspaceHeader } from './helpers/files.js'\n// eslint-disable-next-line import/no-unresolved, n/no-missing-import\nimport 'vite/modulepreload-polyfill'\n\nconst workspaceAvailable = loadState('text', 'workspace_available')\n\nregisterDavProperty('nc:rich-workspace-flat', { nc: 'http://nextcloud.org/ns' })\nregisterDavProperty('nc:rich-workspace-file-flat', { nc: 'http://nextcloud.org/ns' })\n\nif (workspaceAvailable) {\n\taddMenuRichWorkspace()\n\tregisterFileListHeader(FilesWorkspaceHeader)\n}\n"],"file":"text-init.mjs"}