{"version":3,"file":"FilePicker-C1yRZfLt.mjs","sources":["../../node_modules/vue-material-design-icons/File.vue","../../node_modules/vue-material-design-icons/MenuDown.vue","../../node_modules/vue-material-design-icons/MenuUp.vue","../../node_modules/vue-material-design-icons/Folder.vue","../../lib/components/FilePicker/FilePreview.vue","../../lib/components/FilePicker/FileListRow.vue","../../lib/components/FilePicker/LoadingTableRow.vue","../../lib/composables/filesSettings.ts","../../lib/components/FilePicker/FileList.vue","../../node_modules/vue-material-design-icons/Home.vue","../../node_modules/vue-material-design-icons/Plus.vue","../../lib/components/FilePicker/FilePickerBreadcrumbs.vue","../../node_modules/vue-material-design-icons/Close.vue","../../node_modules/vue-material-design-icons/Magnify.vue","../../lib/composables/views.ts","../../lib/components/FilePicker/FilePickerNavigation.vue","../../lib/utils/dav.ts","../../lib/composables/dav.ts","../../lib/composables/mime.ts","../../lib/components/FilePicker/FilePicker.vue"],"sourcesContent":["<template>\n  <span v-bind=\"$attrs\"\n        :aria-hidden=\"title ? null : 'true'\"\n        :aria-label=\"title\"\n        class=\"material-design-icon file-icon\"\n        role=\"img\"\n        @click=\"$emit('click', $event)\">\n    <svg :fill=\"fillColor\"\n         class=\"material-design-icon__svg\"\n         :width=\"size\"\n         :height=\"size\"\n         viewBox=\"0 0 24 24\">\n      <path d=\"M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z\">\n        <title v-if=\"title\">{{ title }}</title>\n      </path>\n    </svg>\n  </span>\n</template>\n\n<script>\nexport default {\n  name: \"FileIcon\",\n  emits: ['click'],\n  props: {\n    title: {\n      type: String,\n    },\n    fillColor: {\n      type: String,\n      default: \"currentColor\"\n    },\n    size: {\n      type: Number,\n      default: 24\n    }\n  }\n}\n</script>","<template>\n  <span v-bind=\"$attrs\"\n        :aria-hidden=\"title ? null : 'true'\"\n        :aria-label=\"title\"\n        class=\"material-design-icon menu-down-icon\"\n        role=\"img\"\n        @click=\"$emit('click', $event)\">\n    <svg :fill=\"fillColor\"\n         class=\"material-design-icon__svg\"\n         :width=\"size\"\n         :height=\"size\"\n         viewBox=\"0 0 24 24\">\n      <path d=\"M7,10L12,15L17,10H7Z\">\n        <title v-if=\"title\">{{ title }}</title>\n      </path>\n    </svg>\n  </span>\n</template>\n\n<script>\nexport default {\n  name: \"MenuDownIcon\",\n  emits: ['click'],\n  props: {\n    title: {\n      type: String,\n    },\n    fillColor: {\n      type: String,\n      default: \"currentColor\"\n    },\n    size: {\n      type: Number,\n      default: 24\n    }\n  }\n}\n</script>","<template>\n  <span v-bind=\"$attrs\"\n        :aria-hidden=\"title ? null : 'true'\"\n        :aria-label=\"title\"\n        class=\"material-design-icon menu-up-icon\"\n        role=\"img\"\n        @click=\"$emit('click', $event)\">\n    <svg :fill=\"fillColor\"\n         class=\"material-design-icon__svg\"\n         :width=\"size\"\n         :height=\"size\"\n         viewBox=\"0 0 24 24\">\n      <path d=\"M7,15L12,10L17,15H7Z\">\n        <title v-if=\"title\">{{ title }}</title>\n      </path>\n    </svg>\n  </span>\n</template>\n\n<script>\nexport default {\n  name: \"MenuUpIcon\",\n  emits: ['click'],\n  props: {\n    title: {\n      type: String,\n    },\n    fillColor: {\n      type: String,\n      default: \"currentColor\"\n    },\n    size: {\n      type: Number,\n      default: 24\n    }\n  }\n}\n</script>","<template>\n  <span v-bind=\"$attrs\"\n        :aria-hidden=\"title ? null : 'true'\"\n        :aria-label=\"title\"\n        class=\"material-design-icon folder-icon\"\n        role=\"img\"\n        @click=\"$emit('click', $event)\">\n    <svg :fill=\"fillColor\"\n         class=\"material-design-icon__svg\"\n         :width=\"size\"\n         :height=\"size\"\n         viewBox=\"0 0 24 24\">\n      <path d=\"M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z\">\n        <title v-if=\"title\">{{ title }}</title>\n      </path>\n    </svg>\n  </span>\n</template>\n\n<script>\nexport default {\n  name: \"FolderIcon\",\n  emits: ['click'],\n  props: {\n    title: {\n      type: String,\n    },\n    fillColor: {\n      type: String,\n      default: \"currentColor\"\n    },\n    size: {\n      type: Number,\n      default: 24\n    }\n  }\n}\n</script>","<!--\n  - SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors\n  - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n<template>\n\t<div\n\t\t:style=\"previewLoaded ? { backgroundImage: `url(${previewURL})` } : undefined\"\n\t\t:class=\"fileListIconStyles['file-picker__file-icon']\">\n\t\t<template v-if=\"!previewLoaded\">\n\t\t\t<IconFile v-if=\"isFile\" :size=\"32\" />\n\t\t\t<template v-else>\n\t\t\t\t<NcIconSvgWrapper\n\t\t\t\t\tv-if=\"folderDecorationIcon\"\n\t\t\t\t\t:class=\"fileListIconStyles['file-picker__file-icon-overlay']\"\n\t\t\t\t\tinline\n\t\t\t\t\t:path=\"folderDecorationIcon\"\n\t\t\t\t\t:size=\"16\" />\n\t\t\t\t<IconFolder\n\t\t\t\t\t:class=\"fileListIconStyles['file-picker__file-icon--primary']\"\n\t\t\t\t\t:size=\"32\" />\n\t\t\t</template>\n\t\t</template>\n\t</div>\n</template>\n\n<script setup lang=\"ts\">\nimport type { INode } from '@nextcloud/files'\n\nimport { mdiAccountGroupOutline, mdiAccountPlus, mdiKey, mdiLink, mdiNetworkOutline, mdiTagOutline } from '@mdi/js'\nimport { FileType } from '@nextcloud/files'\nimport { ShareType } from '@nextcloud/sharing'\nimport { computed, ref, toRef } from 'vue'\nimport NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'\nimport IconFile from 'vue-material-design-icons/File.vue'\nimport IconFolder from 'vue-material-design-icons/Folder.vue'\nimport { usePreviewURL } from '../../composables/preview.ts'\n\n// CSS modules\nimport fileListIconStylesModule from './FileListIcon.module.scss'\n\nconst props = defineProps<{\n\t/**\n\t * Node to show preview of\n\t */\n\tnode: INode\n\t/**\n\t * Crop the preview to fit the container or preserve original aspect ratio\n\t */\n\tcropImagePreviews: boolean\n}>()\n\n// workaround for vue2.7 bug, can be removed with vue3\nconst fileListIconStyles = ref(fileListIconStylesModule)\n\nconst {\n\tpreviewURL,\n\tpreviewLoaded,\n} = usePreviewURL(toRef(props, 'node'), computed(() => ({ cropPreview: props.cropImagePreviews })))\n\nconst isFile = computed(() => props.node.type === FileType.File)\nconst folderDecorationIcon = computed(() => {\n\tif (props.node.type !== FileType.Folder) {\n\t\treturn null\n\t}\n\n\t// Encrypted folders\n\tif (props.node.attributes?.['is-encrypted'] === 1) {\n\t\treturn mdiKey\n\t}\n\n\t// System tags\n\tif (props.node.attributes?.['is-tag']) {\n\t\treturn mdiTagOutline\n\t}\n\n\t// Link and mail shared folders\n\tconst shareTypes = Object.values(props.node.attributes?.['share-types'] || {}).flat() as number[]\n\tif (shareTypes.some((type) => type === ShareType.Link || type === ShareType.Email)) {\n\t\treturn mdiLink\n\t}\n\n\t// Shared folders\n\tif (shareTypes.length > 0) {\n\t\treturn mdiAccountPlus\n\t}\n\n\tswitch (props.node.attributes?.['mount-type']) {\n\t\tcase 'external':\n\t\tcase 'external-session':\n\t\t\treturn mdiNetworkOutline\n\t\tcase 'group':\n\t\t\treturn mdiAccountGroupOutline\n\t\tcase 'shared':\n\t\t\treturn mdiAccountPlus\n\t}\n\n\treturn null\n})\n</script>\n","<!--\n  - SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors\n  - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n<template>\n\t<tr\n\t\t:tabindex=\"(showCheckbox && !isDirectory) ? undefined : 0\"\n\t\t:aria-selected=\"!isPickable ? undefined : selected\"\n\t\tclass=\"file-picker__row\"\n\t\t:class=\"[\n\t\t\t{\n\t\t\t\t'file-picker__row--selected': selected && !showCheckbox,\n\t\t\t\t'file-picker__row--not-navigatable': isDirectory && !isNavigatable,\n\t\t\t\t'file-picker__row--not-pickable': !isPickable,\n\t\t\t},\n\t\t]\"\n\t\t:data-filename=\"node.basename\"\n\t\tdata-testid=\"file-list-row\"\n\t\tv-on=\"{\n\t\t\tclick: handleClick,\n\t\t\t/* same as tabindex -> if we hide the checkbox or this is a directory we need keyboard access to enter the directory or select the node */\n\t\t\t...(!showCheckbox || isDirectory ? { keydown: handleKeyDown } : {}),\n\t\t}\">\n\t\t<td v-if=\"showCheckbox\" class=\"row-checkbox\" @click.stop=\"() => { /* Stop the click event */ }\">\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t:aria-label=\"t('Select the row for {nodename}', { nodename: displayName })\"\n\t\t\t\t:disabled=\"!isPickable\"\n\t\t\t\tdata-testid=\"row-checkbox\"\n\t\t\t\t:modelValue=\"selected\"\n\t\t\t\t@update:modelValue=\"toggleSelected\" />\n\t\t</td>\n\t\t<td class=\"row-name\">\n\t\t\t<div class=\"file-picker__name-container\" data-testid=\"row-name\">\n\t\t\t\t<FilePreview :node=\"node\" :cropImagePreviews=\"cropImagePreviews\" />\n\t\t\t\t<div class=\"file-picker__file-name\" :title=\"displayName\" v-text=\"displayName\" />\n\t\t\t\t<div class=\"file-picker__file-extension\" v-text=\"fileExtension\" />\n\t\t\t</div>\n\t\t</td>\n\t\t<td class=\"row-size\">\n\t\t\t{{ formatFileSize(node.size || 0) }}\n\t\t</td>\n\t\t<td class=\"row-modified\">\n\t\t\t<NcDateTime :timestamp ignoreSeconds />\n\t\t</td>\n\t</tr>\n</template>\n\n<script setup lang=\"ts\">\nimport type { INode } from '@nextcloud/files'\n\nimport { FileType, formatFileSize, Permission } from '@nextcloud/files'\nimport { extname } from '@nextcloud/paths'\nimport { computed } from 'vue'\nimport NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'\nimport NcDateTime from '@nextcloud/vue/components/NcDateTime'\nimport FilePreview from './FilePreview.vue'\nimport { t } from '../../utils/l10n.ts'\n\nconst props = defineProps<{\n\t/** Can directories be picked */\n\tallowPickDirectory: boolean\n\t/** Is this node currently selected */\n\tselected: boolean\n\t/** Whether to show the checkbox in first column */\n\tshowCheckbox: boolean\n\t/** Whether the node can be picked */\n\tcanPick: boolean\n\t/** The current node */\n\tnode: INode\n\t/** Whether the preview should be cropped */\n\tcropImagePreviews: boolean\n}>()\n\nconst emit = defineEmits<{\n\t/** Emitted when the selected state is changed */\n\t'update:selected': [selected: boolean]\n\t/** Emitted when a directory was not selected but entered */\n\tenterDirectory: [node: INode]\n}>()\n\nconst timestamp = computed(() => props.node.mtime ?? 0)\n\n/**\n * The file extension of the file\n */\nconst fileExtension = computed(() => extname(props.node.displayname))\n\n/**\n * The displayname of the current node (excluding file extension)\n */\nconst displayName = computed(() => props.node.displayname.slice(0, fileExtension.value ? -fileExtension.value.length : undefined))\n\n/**\n * Check if the node is a directory\n */\nconst isDirectory = computed(() => props.node.type === FileType.Folder)\n\n/**\n * If this node can be picked, basically just check if picking a directory is allowed\n */\nconst isPickable = computed(() => props.canPick && (props.allowPickDirectory || !isDirectory.value))\n\n/**\n * If this node is not readable, then we cannot navigate to it.\n */\nconst isNavigatable = computed(() => (props.node.permissions & Permission.READ) === Permission.READ)\n\n/**\n * Toggle the selection state\n */\nfunction toggleSelected() {\n\tif (!isPickable.value) {\n\t\treturn\n\t}\n\n\temit('update:selected', !props.selected)\n}\n\n/**\n * Handle clicking the table row, if it is a directory it is opened, else selected\n */\nfunction handleClick() {\n\tif (isDirectory.value) {\n\t\tif (isNavigatable.value) {\n\t\t\temit('enterDirectory', props.node)\n\t\t}\n\t} else {\n\t\ttoggleSelected()\n\t}\n}\n\n/**\n * Handle keydown on the table row, pressing the enter key will be similar to clicking for keyboard navigation\n *\n * @param event The Keydown event\n */\nfunction handleKeyDown(event: KeyboardEvent) {\n\tif (event.key === 'Enter') {\n\t\thandleClick()\n\t}\n}\n</script>\n\n<style scoped lang=\"scss\">\n@use './FileList';\n\n.file-picker {\n\t&__row {\n\t\t* {\n\t\t\tcursor: pointer;\n\t\t}\n\n\t\t&--selected {\n\t\t\tbackground-color: var(--color-background-dark);\n\t\t}\n\n\t\t&--not-navigatable {\n\t\t\tfilter: saturate(0.7);\n\t\t\topacity: 0.7;\n\t\t}\n\n\t\t&--not-navigatable,\n\t\t&--not-pickable {\n\n\t\t\t* {\n\t\t\t\tcursor: default !important;\n\t\t\t}\n\t\t}\n\n\t\t&:hover {\n\t\t\tbackground-color: var(--color-background-hover);\n\t\t}\n\t}\n\n\t&__name-container {\n\t\tdisplay: flex;\n\t\tjustify-content: start;\n\t\talign-items: center;\n\t\theight: 100%;\n\t}\n\n\t&__file-name {\n\t\tpadding-inline-start: 6px;\n\t\tmin-width: 0;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t}\n\n\t&__file-extension {\n\t\tcolor: var(--color-text-maxcontrast);\n\t\tmin-width: fit-content;\n\t}\n}\n</style>\n","<!--\n  - SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n  - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n<!-- Simple component to fake a loading table row with placeholders -->\n<template>\n\t<tr aria-hidden=\"true\" class=\"file-picker__row loading-row\">\n\t\t<td v-if=\"showCheckbox\" class=\"row-checkbox\">\n\t\t\t<span />\n\t\t</td>\n\t\t<td class=\"row-name\">\n\t\t\t<div class=\"row-wrapper\">\n\t\t\t\t<span :class=\"fileListIconStyles['file-picker__file-icon']\" />\n\t\t\t\t<span />\n\t\t\t</div>\n\t\t</td>\n\t\t<td class=\"row-size\">\n\t\t\t<span />\n\t\t</td>\n\t\t<td class=\"row-modified\">\n\t\t\t<span />\n\t\t</td>\n\t</tr>\n</template>\n\n<script setup lang=\"ts\">\nimport fileListIconStyles from './FileListIcon.module.scss'\n\ndefineProps<{\n\t/**\n\t * Does the filelist use the checkbox column\n\t */\n\tshowCheckbox: boolean\n}>()\n</script>\n\n<style scoped lang=\"scss\">\n@use './FileList';\n\n@keyframes gradient {\n\t0% {\n\t\tbackground-position: 0% 50%;\n\t}\n\t50% {\n\t\tbackground-position: 100% 50%;\n\t}\n\t100% {\n\t\tbackground-position: 0% 50%;\n\t}\n}\n\n.loading-row {\n\t.row-checkbox {\n\t\ttext-align: center!important;\n\t}\n\n\tspan {\n\t\tdisplay: inline-block;\n\t\theight: 24px;\n\n\t\tbackground: linear-gradient(to right,var(--color-background-darker),var(--color-text-maxcontrast),var(--color-background-darker));\n\t\tbackground-size: 600px 100%;\n\t\tborder-radius: var(--border-radius);\n\t\tanimation: gradient 12s ease infinite;\n\t}\n\n\t.row-wrapper {\n\t\tdisplay: inline-flex;\n\t\talign-items: center;\n\t}\n\n\t.row-checkbox span {\n\t\twidth: 24px;\n\t}\n\n\t.row-name span:last-of-type {\n\t\tmargin-inline-start: 6px;\n\t\twidth: 130px;\n\t}\n\n\t.row-size span {\n\t\twidth: 80px;\n\t}\n\n\t.row-modified span {\n\t\twidth: 90px;\n\t}\n}\n</style>\n","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { ComputedRef, Ref } from 'vue'\n\nimport axios from '@nextcloud/axios'\nimport { loadState } from '@nextcloud/initial-state'\nimport { generateUrl } from '@nextcloud/router'\nimport { isPublicShare } from '@nextcloud/sharing/public'\nimport { computed, onMounted, ref, toValue } from 'vue'\nimport { showError } from '../toast.ts'\nimport { t } from '../utils/l10n.ts'\nimport { logger } from '../utils/logger.ts'\n\ninterface OCAFilesUserConfig {\n\tshow_hidden: boolean\n\tcrop_image_previews: boolean\n\tsort_favorites_first: boolean\n}\n\ninterface OCAFilesView {\n\tsorting_direction: 'asc' | 'desc'\n\tsorting_mode: 'basename' | 'size' | 'mtime'\n}\n\ninterface OCAFilesViewConfig {\n\t[view: string]: OCAFilesView\n}\n\ninterface ViewConfig {\n\tsortBy: 'basename' | 'size' | 'mtime'\n\torder: 'ascending' | 'descending' | 'none'\n}\n\nexport type FileListViews = 'files' | 'recent' | 'favorites'\n\n/**\n * Composable to get the files app settings\n * (show hidden files, sort favorites, crop previews)\n */\nexport function useFilesSettings() {\n\tconst filesUserState = loadState<OCAFilesUserConfig | null>('files', 'config', null)\n\n\tconst showHiddenFiles = ref(filesUserState?.show_hidden ?? true)\n\tconst sortFavoritesFirst = ref(filesUserState?.sort_favorites_first ?? true)\n\tconst cropImagePreviews = ref(filesUserState?.crop_image_previews ?? true)\n\n\tonMounted(async () => {\n\t\tif (!isPublicShare()) {\n\t\t\ttry {\n\t\t\t\tconst { data } = await axios.get(generateUrl('/apps/files/api/v1/configs'))\n\n\t\t\t\tshowHiddenFiles.value = data?.data?.show_hidden ?? false\n\t\t\t\tsortFavoritesFirst.value = data?.data?.sort_favorites_first ?? true\n\t\t\t\tcropImagePreviews.value = data?.data?.crop_image_previews ?? true\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error('Could not load files settings', { error })\n\t\t\t\tshowError(t('Could not load files settings'))\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.debug('Skip loading files settings - currently on public share')\n\t\t}\n\t})\n\n\treturn {\n\t\tshowHiddenFiles,\n\t\tsortFavoritesFirst,\n\t\tcropImagePreviews,\n\t}\n}\n\n/**\n * Composable to get the files app view configs for sorting the files list\n *\n * @param currentView the currently active view\n */\nexport function useFilesViews(currentView?: FileListViews | Ref<FileListViews> | ComputedRef<FileListViews>) {\n\tconst convertOrder = (order?: string) => order === 'asc' ? 'ascending' : (order === 'desc' ? 'descending' : 'none')\n\n\tconst filesViewsState = loadState<OCAFilesViewConfig | null>('files', 'viewConfigs', null)\n\n\tconst filesViewConfig = ref<ViewConfig>({\n\t\tsortBy: filesViewsState?.files?.sorting_mode ?? 'basename',\n\t\torder: convertOrder(filesViewsState?.files?.sorting_direction ?? 'asc'),\n\t})\n\tconst recentViewConfig = ref<ViewConfig>({\n\t\tsortBy: filesViewsState?.recent?.sorting_mode ?? 'basename',\n\t\torder: convertOrder(filesViewsState?.recent?.sorting_direction ?? 'asc'),\n\t})\n\tconst favoritesViewConfig = ref<ViewConfig>({\n\t\tsortBy: filesViewsState?.favorites?.sorting_mode ?? 'basename',\n\t\torder: convertOrder(filesViewsState?.favorites?.sorting_direction ?? 'asc'),\n\t})\n\n\tonMounted(async () => {\n\t\tif (!isPublicShare()) {\n\t\t\ttry {\n\t\t\t\tconst { data } = await axios.get(generateUrl('/apps/files/api/v1/views'))\n\t\t\t\tfilesViewConfig.value = {\n\t\t\t\t\tsortBy: data?.data?.files?.sorting_mode ?? 'basename',\n\t\t\t\t\torder: convertOrder(data?.data?.files?.sorting_direction),\n\t\t\t\t}\n\t\t\t\tfavoritesViewConfig.value = {\n\t\t\t\t\tsortBy: data?.data?.favorites?.sorting_mode ?? 'basename',\n\t\t\t\t\torder: convertOrder(data?.data?.favorites?.sorting_direction),\n\t\t\t\t}\n\t\t\t\trecentViewConfig.value = {\n\t\t\t\t\tsortBy: data?.data?.recent?.sorting_mode ?? 'basename',\n\t\t\t\t\torder: convertOrder(data?.data?.recent?.sorting_direction),\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error('Could not load files views', { error })\n\t\t\t\tshowError(t('Could not load files views'))\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.debug('Skip loading files views - currently on public share')\n\t\t}\n\t})\n\n\tconst currentConfig = computed(() => toValue(currentView || 'files') === 'files' ? filesViewConfig.value : (toValue(currentView) === 'recent' ? recentViewConfig.value : favoritesViewConfig.value))\n\tconst sortBy = computed(() => currentConfig.value.sortBy)\n\tconst order = computed(() => currentConfig.value.order)\n\n\treturn {\n\t\tfilesViewConfig,\n\t\tfavoritesViewConfig,\n\t\trecentViewConfig,\n\t\tcurrentConfig,\n\t\tsortBy,\n\t\torder,\n\t}\n}\n","<!--\n  - SPDX-FileCopyrightText: 2020-2024 Nextcloud GmbH and Nextcloud contributors\n  - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n<template>\n\t<div ref=\"fileContainer\" class=\"file-picker__files\">\n\t\t<table>\n\t\t\t<thead>\n\t\t\t\t<tr>\n\t\t\t\t\t<th v-if=\"multiselect\" class=\"row-checkbox\">\n\t\t\t\t\t\t<span class=\"hidden-visually\">\n\t\t\t\t\t\t\t{{ t('Select entry') }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\tv-if=\"multiselect\"\n\t\t\t\t\t\t\t:aria-label=\"t('Select all entries')\"\n\t\t\t\t\t\t\tdata-testid=\"select-all-checkbox\"\n\t\t\t\t\t\t\t:modelValue=\"allSelected\"\n\t\t\t\t\t\t\t@update:modelValue=\"onSelectAll\" />\n\t\t\t\t\t</th>\n\t\t\t\t\t<th :aria-sort=\"sortByName\" class=\"row-name\">\n\t\t\t\t\t\t<div class=\"header-wrapper\">\n\t\t\t\t\t\t\t<span class=\"file-picker__header-preview\" />\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tdata-test=\"file-picker_sort-name\"\n\t\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t\twide\n\t\t\t\t\t\t\t\t@click=\"toggleSorting('basename')\">\n\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t<IconSortAscending v-if=\"sortByName === 'ascending'\" :size=\"20\" />\n\t\t\t\t\t\t\t\t\t<IconSortDescending v-else-if=\"sortByName === 'descending'\" :size=\"20\" />\n\t\t\t\t\t\t\t\t\t<span v-else style=\"width: 44px\" />\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t{{ t('Name') }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</th>\n\t\t\t\t\t<th :aria-sort=\"sortBySize\" class=\"row-size\">\n\t\t\t\t\t\t<NcButton variant=\"tertiary\" wide @click=\"toggleSorting('size')\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<IconSortAscending v-if=\"sortBySize === 'ascending'\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<IconSortDescending v-else-if=\"sortBySize === 'descending'\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<span v-else style=\"width: 44px\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ t('Size') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</th>\n\t\t\t\t\t<th :aria-sort=\"sortByModified\" class=\"row-modified\">\n\t\t\t\t\t\t<NcButton variant=\"tertiary\" wide @click=\"toggleSorting('mtime')\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<IconSortAscending v-if=\"sortByModified === 'ascending'\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<IconSortDescending v-else-if=\"sortByModified === 'descending'\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<span v-else style=\"width: 44px\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ t('Modified') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</th>\n\t\t\t\t</tr>\n\t\t\t</thead>\n\t\t\t<tbody>\n\t\t\t\t<template v-if=\"loading\">\n\t\t\t\t\t<LoadingTableRow v-for=\"index in skeletonNumber\" :key=\"index\" :showCheckbox=\"multiselect\" />\n\t\t\t\t</template>\n\t\t\t\t<template v-else>\n\t\t\t\t\t<FileListRow\n\t\t\t\t\t\tv-for=\"file of sortedFiles\"\n\t\t\t\t\t\t:key=\"file.fileid || file.path\"\n\t\t\t\t\t\t:allowPickDirectory=\"allowPickDirectory\"\n\t\t\t\t\t\t:showCheckbox=\"multiselect\"\n\t\t\t\t\t\t:canPick=\"(multiselect || selectedFiles.length === 0 || selectedFiles.includes(file)) && (canPick === undefined || canPick(file))\"\n\t\t\t\t\t\t:selected=\"selectedFiles.includes(file)\"\n\t\t\t\t\t\t:node=\"file\"\n\t\t\t\t\t\t:cropImagePreviews=\"cropImagePreviews\"\n\t\t\t\t\t\t@update:selected=\"onNodeSelected(file)\"\n\t\t\t\t\t\t@enterDirectory=\"onChangeDirectory\" />\n\t\t\t\t</template>\n\t\t\t</tbody>\n\t\t</table>\n\t</div>\n</template>\n\n<script setup lang=\"ts\">\nimport type { INode } from '@nextcloud/files'\nimport type { FileListViews } from '../../composables/filesSettings.ts'\nimport type { IFilePickerCanPick } from '../types.ts'\n\nimport { FileType, sortNodes } from '@nextcloud/files'\nimport { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'\nimport NcButton from '@nextcloud/vue/components/NcButton'\nimport NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'\nimport IconSortDescending from 'vue-material-design-icons/MenuDown.vue'\nimport IconSortAscending from 'vue-material-design-icons/MenuUp.vue'\nimport FileListRow from './FileListRow.vue'\nimport LoadingTableRow from './LoadingTableRow.vue'\nimport { useFilesSettings, useFilesViews } from '../../composables/filesSettings.ts'\nimport { t } from '../../utils/l10n.ts'\n\n/**\n * Current path\n */\nconst path = defineModel<string>('path', { required: true })\n\n/**\n * Currently selected files\n */\nconst selectedFiles = defineModel<INode[]>('selectedFiles', { required: true })\n\nconst props = defineProps<{\n\t/**\n\t * Current view\n\t */\n\tcurrentView: FileListViews\n\t/**\n\t * Allow selecting multiple elements\n\t */\n\tmultiselect: boolean\n\t/**\n\t * Allow picking directories\n\t */\n\tallowPickDirectory: boolean\n\t/**\n\t * Is in loading state (WebDAV request ongoing)\n\t */\n\tloading: boolean\n\t/**\n\t * Files to show\n\t */\n\tfiles: INode[]\n\t/**\n\t * Custom function to decide if a node can be picked\n\t */\n\tcanPick?: IFilePickerCanPick\n}>()\n\n/// sorting related stuff\n\ntype ISortingAttributes = 'basename' | 'size' | 'mtime'\ntype ISortingOrder = 'ascending' | 'descending' | 'none'\n\n/** Override files app sorting */\nconst customSortingConfig = ref<{ sortBy: ISortingAttributes, order: ISortingOrder }>()\n/** The current sorting of the files app */\nconst { currentConfig: filesAppSorting } = useFilesViews(props.currentView)\n/** Wrapper that uses custom sorting, but fallsback to the files app */\nconst sortingConfig = computed(() => customSortingConfig.value ?? filesAppSorting.value)\n\n// Some helpers for the template\nconst sortByName = computed(() => sortingConfig.value.sortBy === 'basename' ? (sortingConfig.value.order === 'none' ? undefined : sortingConfig.value.order) : undefined)\nconst sortBySize = computed(() => sortingConfig.value.sortBy === 'size' ? (sortingConfig.value.order === 'none' ? undefined : sortingConfig.value.order) : undefined)\nconst sortByModified = computed(() => sortingConfig.value.sortBy === 'mtime' ? (sortingConfig.value.order === 'none' ? undefined : sortingConfig.value.order) : undefined)\n\n/**\n * @param sortBy - The attributes to sort by\n */\nfunction toggleSorting(sortBy: ISortingAttributes) {\n\tif (sortingConfig.value.sortBy === sortBy) {\n\t\tif (sortingConfig.value.order === 'ascending') {\n\t\t\tcustomSortingConfig.value = { sortBy: sortingConfig.value.sortBy, order: 'descending' }\n\t\t} else {\n\t\t\tcustomSortingConfig.value = { sortBy: sortingConfig.value.sortBy, order: 'ascending' }\n\t\t}\n\t} else {\n\t\tcustomSortingConfig.value = { sortBy, order: 'ascending' }\n\t}\n}\n\nconst { sortFavoritesFirst, cropImagePreviews } = useFilesSettings()\n\n/**\n * Files sorted by columns\n */\nconst sortedFiles = computed(() => {\n\treturn sortNodes(props.files, {\n\t\tsortFoldersFirst: true,\n\t\tsortFavoritesFirst: sortFavoritesFirst.value,\n\t\tsortingOrder: sortingConfig.value.order === 'descending' ? 'desc' : 'asc',\n\t\tsortingMode: sortingConfig.value.sortBy,\n\t})\n})\n\n/**\n * Contains the selectable files, filtering out directories if `allowPickDirectory` is not set\n */\nconst selectableFiles = computed(() => props.files.filter((file) => props.allowPickDirectory || file.type !== FileType.Folder))\n\n/**\n * Whether all selectable files are currently selected\n */\nconst allSelected = computed(() => !props.loading && selectedFiles.value.length > 0 && selectedFiles.value.length >= selectableFiles.value.length)\n\n/**\n * Handle the \"select all\" checkbox\n */\nfunction onSelectAll() {\n\tif (selectedFiles.value.length < selectableFiles.value.length) {\n\t\t// If not all selected, select all\n\t\tselectedFiles.value = [...selectableFiles.value]\n\t} else {\n\t\t// If already all selected, deselect all\n\t\tselectedFiles.value = []\n\t}\n}\n\n/**\n * Handle selecting a node on the files list\n *\n * @param file the selected node\n */\nfunction onNodeSelected(file: INode) {\n\tif (selectedFiles.value.includes(file)) {\n\t\tselectedFiles.value = selectedFiles.value.filter((f) => f.path !== file.path)\n\t} else {\n\t\tif (props.multiselect) {\n\t\t\tselectedFiles.value = [...selectedFiles.value, file]\n\t\t} else {\n\t\t\t// no multi select so only this file is selected\n\t\t\tselectedFiles.value = [file]\n\t\t}\n\t}\n}\n\n/**\n * Emit the new current path\n *\n * @param dir The directory that is entered\n */\nfunction onChangeDirectory(dir: INode) {\n\tpath.value = dir.path\n}\n\n/**\n * Number of loading skeletons to use to fill the filepicker\n */\nconst skeletonNumber = ref(4)\nconst fileContainer = ref<HTMLDivElement>()\n{\n\tconst resize = () => nextTick(() => {\n\t\tconst nodes = fileContainer.value?.parentElement?.children || []\n\t\tlet height = fileContainer.value?.parentElement?.clientHeight || 450\n\t\tfor (let index = 0; index < nodes.length; index++) {\n\t\t\tif (!fileContainer.value?.isSameNode(nodes[index]!)) {\n\t\t\t\theight -= nodes[index]!.clientHeight\n\t\t\t}\n\t\t}\n\t\t// container height - 50px table header / row height of 50px\n\t\tskeletonNumber.value = Math.max(1, Math.floor((height - 50) / 50))\n\t})\n\tonMounted(() => {\n\t\twindow.addEventListener('resize', resize)\n\t\tresize()\n\t})\n\tonUnmounted(() => {\n\t\twindow.removeEventListener('resize', resize)\n\t})\n}\n</script>\n\n<style scoped lang=\"scss\">\n.file-picker {\n\t&__header-preview {\n\t\twidth: 22px; // 32px - 16px padding of button + 6px padding in file list rows\n\t\theight: 32px;\n\t\tflex: 0 0 auto; // do not shrink or grow\n\t}\n\n\t&__files {\n\t\t// ensure focus outlines are visible\n\t\tmargin: 2px;\n\t\tmargin-inline-start: 12px; // align with bread crumbs\n\t\toverflow: scroll auto;\n\n\t\ttable {\n\t\t\twidth: 100%;\n\t\t\tmax-height: 100%;\n\t\t\ttable-layout: fixed;\n\t\t}\n\t\tth {\n\t\t\tposition: sticky;\n\t\t\tz-index: 1; // show on top of scrolled content rows\n\t\t\ttop: 0;\n\t\t\tbackground-color: var(--color-main-background);\n\t\t\t// ensure focus outline of buttons is visible\n\t\t\tpadding: 2px;\n\n\t\t\t.header-wrapper {\n\t\t\t\tdisplay: flex;\n\t\t\t}\n\n\t\t\t&.row-checkbox {\n\t\t\t\twidth: 44px;\n\t\t\t}\n\t\t\t&.row-name {\n\t\t\t\twidth: 230px;\n\t\t\t}\n\t\t\t&.row-size {\n\t\t\t\twidth: 100px;\n\t\t\t}\n\t\t\t&.row-modified {\n\t\t\t\twidth: 120px;\n\t\t\t}\n\t\t}\n\n\t\t// >> begin of hacks for table header sorting buttons\n\t\t// TODO: Remove this hack after ... is available\n\t\tth:not(.row-size) {\n\t\t\t:deep(.button-vue__wrapper) {\n\t\t\t\tjustify-content: start;\n\t\t\t\tflex-direction: row-reverse;\n\t\t\t}\n\t\t\t:deep(.button-vue) {\n\t\t\t\tpadding-inline: 16px 4px;\n\t\t\t}\n\t\t}\n\t\tth.row-size :deep(.button-vue__wrapper) {\n\t\t\tjustify-content: end;\n\t\t}\n\t\tth :deep(.button-vue__wrapper) {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\n\t\t\t.button-vue__text {\n\t\t\t\tfont-weight: normal;\n\t\t\t}\n\t\t}\n\t\t// << end of hacks\n\t}\n}\n</style>\n","<template>\n  <span v-bind=\"$attrs\"\n        :aria-hidden=\"title ? null : 'true'\"\n        :aria-label=\"title\"\n        class=\"material-design-icon home-icon\"\n        role=\"img\"\n        @click=\"$emit('click', $event)\">\n    <svg :fill=\"fillColor\"\n         class=\"material-design-icon__svg\"\n         :width=\"size\"\n         :height=\"size\"\n         viewBox=\"0 0 24 24\">\n      <path d=\"M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z\">\n        <title v-if=\"title\">{{ title }}</title>\n      </path>\n    </svg>\n  </span>\n</template>\n\n<script>\nexport default {\n  name: \"HomeIcon\",\n  emits: ['click'],\n  props: {\n    title: {\n      type: String,\n    },\n    fillColor: {\n      type: String,\n      default: \"currentColor\"\n    },\n    size: {\n      type: Number,\n      default: 24\n    }\n  }\n}\n</script>","<template>\n  <span v-bind=\"$attrs\"\n        :aria-hidden=\"title ? null : 'true'\"\n        :aria-label=\"title\"\n        class=\"material-design-icon plus-icon\"\n        role=\"img\"\n        @click=\"$emit('click', $event)\">\n    <svg :fill=\"fillColor\"\n         class=\"material-design-icon__svg\"\n         :width=\"size\"\n         :height=\"size\"\n         viewBox=\"0 0 24 24\">\n      <path d=\"M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z\">\n        <title v-if=\"title\">{{ title }}</title>\n      </path>\n    </svg>\n  </span>\n</template>\n\n<script>\nexport default {\n  name: \"PlusIcon\",\n  emits: ['click'],\n  props: {\n    title: {\n      type: String,\n    },\n    fillColor: {\n      type: String,\n      default: \"currentColor\"\n    },\n    size: {\n      type: Number,\n      default: 24\n    }\n  }\n}\n</script>","<!--\n  - SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors\n  - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n<template>\n\t<NcBreadcrumbs class=\"file-picker__breadcrumbs\">\n\t\t<template #default>\n\t\t\t<NcBreadcrumb\n\t\t\t\t:name=\"t('All files')\"\n\t\t\t\t:title=\"t('Home')\"\n\t\t\t\t@click=\"path = '/'\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<IconHome :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t</NcBreadcrumb>\n\t\t\t<NcBreadcrumb\n\t\t\t\tv-for=\"dir in pathElements\"\n\t\t\t\t:key=\"dir.path\"\n\t\t\t\t:name=\"dir.name\"\n\t\t\t\t:title=\"dir.path\"\n\t\t\t\t@click=\"path = dir.path\" />\n\t\t</template>\n\t\t<template v-if=\"showMenu\" #actions>\n\t\t\t<NcActions\n\t\t\t\tv-model:open=\"actionsOpen\"\n\t\t\t\t:aria-label=\"t('Create directory')\"\n\t\t\t\t:forceMenu=\"true\"\n\t\t\t\t:forceName=\"true\"\n\t\t\t\t:menuName=\"t('New')\"\n\t\t\t\tvariant=\"secondary\"\n\t\t\t\t@close=\"newNodeName = ''\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<IconPlus :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<NcActionInput\n\t\t\t\t\tref=\"nameInput\"\n\t\t\t\t\tv-model=\"newNodeName\"\n\t\t\t\t\t:label=\"t('New folder')\"\n\t\t\t\t\t:placeholder=\"t('New folder name')\"\n\t\t\t\t\t@submit=\"onSubmit\"\n\t\t\t\t\t@update:modelValue=\"validateInput\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<IconFolder :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcActionInput>\n\t\t\t</NcActions>\n\t\t</template>\n\t</NcBreadcrumbs>\n</template>\n\n<script setup lang=\"ts\">\nimport { InvalidFilenameError, InvalidFilenameErrorReason, validateFilename } from '@nextcloud/files'\nimport { computed, ref, useTemplateRef } from 'vue'\nimport NcActionInput from '@nextcloud/vue/components/NcActionInput'\nimport NcActions from '@nextcloud/vue/components/NcActions'\nimport NcBreadcrumb from '@nextcloud/vue/components/NcBreadcrumb'\nimport NcBreadcrumbs from '@nextcloud/vue/components/NcBreadcrumbs'\nimport IconFolder from 'vue-material-design-icons/Folder.vue'\nimport IconHome from 'vue-material-design-icons/Home.vue'\nimport IconPlus from 'vue-material-design-icons/Plus.vue'\nimport { t } from '../../utils/l10n.ts'\n\n/** Current path to display */\nconst path = defineModel<string>('path', { required: true })\n\ndefineProps<{\n\t/** Whether to show the \"new node\" menu or not */\n\tshowMenu?: boolean\n}>()\n\nconst emit = defineEmits<{\n\t/**\n\t * Triggered when a new directory on the current path should be created\n\t */\n\tcreateNode: [name: string]\n}>()\n\nconst actionsOpen = ref(false)\n\n/**\n * Input on the \"new node\" menu\n */\nconst newNodeName = ref('')\n\nconst nameInput = useTemplateRef('nameInput')\n\n/**\n * Validate user folder name input\n */\nfunction validateInput() {\n\tconst name = newNodeName.value.trim()\n\tconst input = nameInput.value?.$el?.querySelector('input')\n\n\tlet validity = ''\n\ttry {\n\t\tvalidateFilename(name)\n\t} catch (error) {\n\t\tif (!(error instanceof InvalidFilenameError)) {\n\t\t\tthrow error\n\t\t}\n\n\t\tswitch (error.reason) {\n\t\t\tcase InvalidFilenameErrorReason.Character:\n\t\t\t\tvalidity = t('\"{char}\" is not allowed inside a folder name.', { char: error.segment })\n\t\t\t\tbreak\n\t\t\tcase InvalidFilenameErrorReason.ReservedName:\n\t\t\t\tvalidity = t('\"{segment}\" is a reserved name and not allowed for folder names.', { segment: error.segment })\n\t\t\t\tbreak\n\t\t\tcase InvalidFilenameErrorReason.Extension:\n\t\t\t\tvalidity = t('Folder names must not end with \"{extension}\".', { extension: error.segment })\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tvalidity = t('Invalid folder name.')\n\t\t}\n\t}\n\tif (input) {\n\t\tinput.setCustomValidity(validity)\n\t}\n\treturn validity === ''\n}\n/**\n * Handle creating a new node\n */\nfunction onSubmit() {\n\tconst name = newNodeName.value.trim()\n\n\tif (validateInput()) {\n\t\tactionsOpen.value = false\n\t\temit('createNode', name)\n\t\tnewNodeName.value = ''\n\t}\n}\n\n/**\n * Split current path and provide the path and the basename\n */\nconst pathElements = computed(() => path.value.split('/')\n\t.filter((v) => v !== '')\n\t.map((v, i, elements) => ({\n\t\tname: v,\n\t\tpath: '/' + elements.slice(0, i + 1).join('/'),\n\t})))\n</script>\n\n<style scoped lang=\"scss\">\n.file-picker {\n\t&__breadcrumbs {\n\t\t// ensure the breadcrumbs have a static height\n\t\tflex-grow: 0 !important;\n\t}\n}\n</style>\n","<template>\n  <span v-bind=\"$attrs\"\n        :aria-hidden=\"title ? null : 'true'\"\n        :aria-label=\"title\"\n        class=\"material-design-icon close-icon\"\n        role=\"img\"\n        @click=\"$emit('click', $event)\">\n    <svg :fill=\"fillColor\"\n         class=\"material-design-icon__svg\"\n         :width=\"size\"\n         :height=\"size\"\n         viewBox=\"0 0 24 24\">\n      <path d=\"M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z\">\n        <title v-if=\"title\">{{ title }}</title>\n      </path>\n    </svg>\n  </span>\n</template>\n\n<script>\nexport default {\n  name: \"CloseIcon\",\n  emits: ['click'],\n  props: {\n    title: {\n      type: String,\n    },\n    fillColor: {\n      type: String,\n      default: \"currentColor\"\n    },\n    size: {\n      type: Number,\n      default: 24\n    }\n  }\n}\n</script>","<template>\n  <span v-bind=\"$attrs\"\n        :aria-hidden=\"title ? null : 'true'\"\n        :aria-label=\"title\"\n        class=\"material-design-icon magnify-icon\"\n        role=\"img\"\n        @click=\"$emit('click', $event)\">\n    <svg :fill=\"fillColor\"\n         class=\"material-design-icon__svg\"\n         :width=\"size\"\n         :height=\"size\"\n         viewBox=\"0 0 24 24\">\n      <path d=\"M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z\">\n        <title v-if=\"title\">{{ title }}</title>\n      </path>\n    </svg>\n  </span>\n</template>\n\n<script>\nexport default {\n  name: \"MagnifyIcon\",\n  emits: ['click'],\n  props: {\n    title: {\n      type: String,\n    },\n    fillColor: {\n      type: String,\n      default: \"currentColor\"\n    },\n    size: {\n      type: Number,\n      default: 24\n    }\n  }\n}\n</script>","/**\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { ComputedRef, Ref } from 'vue'\n\nimport { mdiClock, mdiFolder, mdiStar } from '@mdi/js'\nimport { t } from '../utils/l10n.ts'\n\nexport type IFilesViewId = 'files' | 'favorites' | 'recent'\n\nexport interface IFilesView {\n\t/**\n\t * Unique ID of the view\n\t */\n\tid: IFilesViewId\n\t/**\n\t * Localized name of the view\n\t */\n\tlabel: string\n\t/**\n\t * The SVG icon paths\n\t */\n\ticon: string\n}\n\n/**\n * Get available file views\n *\n * @param isAnonymous - Whether the user is anonymous\n */\nexport function useViews(isAnonymous: Ref<boolean> | ComputedRef<boolean>) {\n\t/**\n\t * All defined views\n\t */\n\tconst allViews = [\n\t\t{\n\t\t\tid: 'files',\n\t\t\tlabel: t('All files'),\n\t\t\ticon: mdiFolder,\n\t\t},\n\t\t{\n\t\t\tid: 'recent',\n\t\t\tlabel: t('Recent'),\n\t\t\ticon: mdiClock,\n\t\t},\n\t\t{\n\t\t\tid: 'favorites',\n\t\t\tlabel: t('Favorites'),\n\t\t\ticon: mdiStar,\n\t\t},\n\t] as IFilesView[]\n\n\t/**\n\t * Views which are available for the current user\n\t */\n\tconst availableViews = isAnonymous.value ? allViews.filter(({ id }) => id === 'files') : allViews\n\n\treturn {\n\t\tallViews,\n\t\tavailableViews,\n\t}\n}\n","<!--\n  - SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors\n  - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n<template>\n\t<!-- Filter for the file list -->\n\t<NcTextField\n\t\tclass=\"file-picker__filter-input\"\n\t\t:label=\"t('Filter file list')\"\n\t\t:showTrailingButton=\"!!filterString\"\n\t\t:modelValue=\"filterString\"\n\t\t@update:modelValue=\"updateFilterValue\"\n\t\t@trailingButtonClick=\"updateFilterValue('')\">\n\t\t<IconMagnify :size=\"16\" />\n\t\t<template #trailing-button-icon>\n\t\t\t<IconClose :size=\"16\" />\n\t\t</template>\n\t</NcTextField>\n\t<template v-if=\"availableViews.length > 1 && !disabledNavigation\">\n\t\t<!-- On non collapsed dialogs show the tablist, otherwise a dropdown is shown -->\n\t\t<ul\n\t\t\tv-if=\"!isCollapsed\"\n\t\t\tclass=\"file-picker__side\">\n\t\t\t<li v-for=\"view in availableViews\" :key=\"view.id\">\n\t\t\t\t<NcButton\n\t\t\t\t\t:variant=\"currentView === view.id ? 'primary' : 'tertiary'\"\n\t\t\t\t\t:wide=\"true\"\n\t\t\t\t\t@click=\"$emit('update:currentView', view.id)\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<NcIconSvgWrapper :path=\"view.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ view.label }}\n\t\t\t\t</NcButton>\n\t\t\t</li>\n\t\t</ul>\n\t\t<NcSelect\n\t\t\tv-else\n\t\t\t:aria-label=\"t('Current view selector')\"\n\t\t\t:clearable=\"false\"\n\t\t\t:searchable=\"false\"\n\t\t\t:options=\"availableViews\"\n\t\t\t:modelValue=\"currentViewObject\"\n\t\t\t@update:modelValue=\"emit('update:currentView', $event.id)\" />\n\t</template>\n</template>\n\n<script setup lang=\"ts\">\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { computed, ref } from 'vue'\nimport NcButton from '@nextcloud/vue/components/NcButton'\nimport NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'\nimport NcSelect from '@nextcloud/vue/components/NcSelect'\nimport NcTextField from '@nextcloud/vue/components/NcTextField'\nimport IconClose from 'vue-material-design-icons/Close.vue'\nimport IconMagnify from 'vue-material-design-icons/Magnify.vue'\nimport { useViews } from '../../composables/views.ts'\nimport { t } from '../../utils/l10n.ts'\n\nconst props = defineProps<{\n\t/**\n\t * Current view\n\t */\n\tcurrentView: 'files' | 'recent' | 'favorites'\n\t/**\n\t * Current query for filenames\n\t */\n\tfilterString: string\n\t/**\n\t * Collapsed state of the navigation\n\t */\n\tisCollapsed: boolean\n\t/**\n\t * Disabled state of the navigation\n\t */\n\tdisabledNavigation: boolean\n}>()\n\nconst emit = defineEmits<INavigationEvents>()\ninterface INavigationEvents {\n\t(e: 'update:currentView', v: typeof props.currentView): void\n\t(e: 'update:filterString', v: string): void\n}\nconst { availableViews } = useViews(ref(getCurrentUser() === null))\n\n/**\n * The currently active view object\n */\nconst currentViewObject = computed(() => availableViews.filter((v) => v.id === props.currentView)[0] ?? availableViews[0])\n\n/**\n * Propagate current filter value to paren\n *\n * @param value The new filter value\n */\nconst updateFilterValue = (value: string | number) => emit('update:filterString', value.toString())\n</script>\n\n<style scoped lang=\"scss\">\n.file-picker {\n\t&__side {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\talign-items: stretch;\n\t\tgap: 0.5rem;\n\t\tmin-width: 200px;\n\t\t// ensure focus outline is visible\n\t\tpadding: 2px;\n\t\t// align with input\n\t\tmargin-block-start: 7px;\n\t\t// make only the navigation scroll\n\t\toverflow: auto;\n\n\t\t:deep(.button-vue__wrapper) {\n\t\t\tjustify-content: start;\n\t\t}\n\t}\n\n\t&__filter-input {\n\t\t// Align with view title and breadcrumbs\n\t\tmargin-block: 7px; // 36px height + 2x 7px => 50px\n\n\t\tmax-width: 260px;\n\t}\n}\n\n// Ensure filepicker works on mobile\n@media (max-width: 736px) {\n\t.file-picker {\n\t\t&__side {\n\t\t\tflex-direction: row;\n\t\t\tmin-width: unset;\n\t\t}\n\t}\n}\n@media (max-width: 512px) {\n\t.file-picker {\n\t\t&__side {\n\t\t\tflex-direction: row;\n\t\t\tmin-width: unset;\n\n\t\t}\n\t\t&__filter-input {\n\t\t\tmax-width: unset;\n\t\t}\n\t}\n}\n</style>\n\n<style lang=\"scss\">\n/* Ensure focus outline is visible */\n.file-picker__navigation {\n\tpadding-inline: 8px 2px;\n\t&, * {\n\t\tbox-sizing: border-box;\n\t}\n\n\t.v-select.select {\n\t\tmin-width: 220px;\n\t}\n}\n\n@media (min-width: 513px) and (max-width: 736px) {\n\t.file-picker__navigation {\n\t\tgap: 11px;\n\t}\n}\n\n@media (max-width: 512px) {\n\t.file-picker__navigation {\n\t\tflex-direction: column-reverse!important;\n\t}\n}\n</style>\n","/**\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { ContentsWithRoot, Folder, Node } from '@nextcloud/files'\nimport type { FileStat, ResponseDataDetailed, SearchResult, WebDAVClient } from 'webdav'\n\nimport { defaultRootPath, getDefaultPropfind, getRecentSearch, resultToNode } from '@nextcloud/files/dav'\nimport { join } from '@nextcloud/paths'\n\n/**\n * Get the recently changed nodes from the last two weeks\n *\n * @param context - The context\n * @param context.client - The WebDAV client\n * @param context.signal - The abort signal to cancel the request\n */\nexport async function getRecentNodes({ client, signal }: { client: WebDAVClient, signal: AbortSignal }): Promise<Node[]> {\n\t// unix timestamp in seconds, two weeks ago\n\tconst lastTwoWeek = Math.round(Date.now() / 1000) - (60 * 60 * 24 * 14)\n\tconst { data } = await client.search('/', {\n\t\tsignal,\n\t\tdetails: true,\n\t\tdata: getRecentSearch(lastTwoWeek),\n\t}) as ResponseDataDetailed<SearchResult>\n\treturn data.results.map((result: FileStat) => resultToNode(result))\n}\n\n/**\n * Get the directory content\n *\n * @param context - The context\n * @param context.client - The WebDAV client\n * @param context.path - The path to fetch\n * @param context.signal - The abort signal to cancel the request\n */\nexport async function getNodes({ client, path, signal }: { client: WebDAVClient, path: string, signal: AbortSignal }): Promise<ContentsWithRoot> {\n\tconst results = await client.getDirectoryContents(join(defaultRootPath, path), {\n\t\tsignal,\n\t\tdetails: true,\n\t\tincludeSelf: true,\n\t\tdata: getDefaultPropfind(),\n\t}) as ResponseDataDetailed<FileStat[]>\n\tconst nodes = results.data.map((result: FileStat) => resultToNode(result))\n\treturn {\n\t\tcontents: nodes.filter(({ path: nodePath }) => nodePath !== path),\n\t\tfolder: nodes.find(({ path: nodePath }) => path === nodePath) as Folder,\n\t}\n}\n\n/**\n * Get information for one file\n *\n * @param client The WebDAV client\n * @param path The path of the file or folder\n */\nexport async function getFile(client: WebDAVClient, path: string) {\n\tconst { data } = await client.stat(join(defaultRootPath, path), {\n\t\tdetails: true,\n\t\tdata: getDefaultPropfind(),\n\t}) as ResponseDataDetailed<FileStat>\n\treturn resultToNode(data)\n}\n","/*\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IFolder, INode } from '@nextcloud/files'\nimport type { ComputedRef, Ref } from 'vue'\n\nimport { defaultRootPath, getClient, getFavoriteNodes } from '@nextcloud/files/dav'\nimport { join } from '@nextcloud/paths'\nimport { onMounted, ref, shallowRef, watch } from 'vue'\nimport { getFile, getNodes, getRecentNodes } from '../utils/dav.ts'\n\n/**\n * Handle file loading using WebDAV\n *\n * @param currentView Reference to the current files view\n * @param currentPath Reference to the current files path\n */\nexport function useDAVFiles(\n\tcurrentView: Ref<'files' | 'recent' | 'favorites'> | ComputedRef<'files' | 'recent' | 'favorites'>,\n\tcurrentPath: Ref<string> | ComputedRef<string>,\n) {\n\t/**\n\t * The WebDAV client\n\t */\n\tconst client = getClient()\n\n\t/**\n\t * All files in current view and path\n\t */\n\tconst files = shallowRef<INode[]>([] as INode[]) as Ref<INode[]>\n\n\t/**\n\t * The current folder\n\t */\n\tconst folder = shallowRef<IFolder | null>(null)\n\n\t/**\n\t * Loading state of the files\n\t */\n\tconst isLoading = ref(true)\n\n\t/**\n\t * The cancelable promise used internally to cancel on fast navigation\n\t */\n\tlet abortController: AbortController | undefined\n\n\t/**\n\t * Create a new directory in the current path\n\t * The directory will be added to the current file list\n\t *\n\t * @param name Name of the new directory\n\t * @return The created directory\n\t */\n\tasync function createDirectory(name: string): Promise<IFolder> {\n\t\tconst path = join(currentPath.value, name)\n\n\t\tawait client.createDirectory(join(defaultRootPath, path))\n\t\tconst directory = await getFile(client, path) as IFolder\n\t\tfiles.value = [...files.value, directory]\n\t\treturn directory\n\t}\n\n\t/**\n\t * Force reload files using the DAV client\n\t */\n\tasync function loadDAVFiles() {\n\t\tif (abortController) {\n\t\t\tabortController.abort()\n\t\t\tabortController = undefined\n\t\t}\n\n\t\tabortController = new AbortController()\n\t\tisLoading.value = true\n\t\ttry {\n\t\t\tif (currentView.value === 'favorites') {\n\t\t\t\tfiles.value = await getFavoriteNodes({ client, path: currentPath.value, signal: abortController.signal })\n\t\t\t\tfolder.value = null\n\t\t\t} else if (currentView.value === 'recent') {\n\t\t\t\tfiles.value = await getRecentNodes({ client, signal: abortController.signal })\n\t\t\t\tfolder.value = null\n\t\t\t} else {\n\t\t\t\tconst content = await getNodes({ client, path: currentPath.value, signal: abortController.signal })\n\t\t\t\tfolder.value = content.folder\n\t\t\t\tfiles.value = content.contents\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && error.name === 'AbortError') {\n\t\t\t\t// ignore abort errors\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthrow error\n\t\t} finally {\n\t\t\tabortController = undefined\n\t\t\tisLoading.value = false\n\t\t}\n\t}\n\n\t/**\n\t * Watch for ref changes\n\t */\n\twatch([currentView, currentPath], () => loadDAVFiles())\n\n\t/**\n\t * Initial loading of nodes\n\t */\n\tonMounted(() => loadDAVFiles())\n\n\treturn {\n\t\tisLoading,\n\t\tfiles,\n\t\tfolder,\n\t\tloadFiles: loadDAVFiles,\n\t\tcreateDirectory,\n\t}\n}\n","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\nimport type { ComputedRef, Ref } from 'vue'\n\nimport { computed } from 'vue'\n\n/**\n * Create a filter function for MIME types\n * The filter function supports MIME type filters with wildcards\n *\n * @param allowedMIMETypes Reference to allowed MIME types\n */\nexport function useMimeFilter(allowedMIMETypes: Ref<readonly string[]> | ComputedRef<readonly string[]>) {\n\t// Cache splitted MIME types\n\tconst splittedTypes = computed(() => allowedMIMETypes.value.map((filter) => filter.split('/')))\n\n\t/**\n\t * Check if a given MIME type string is supported by the MIME filter values\n\t *\n\t * @param mime MIME type string to check\n\t * @return True if mime is allowed by MIME filter values, false otherwise\n\t */\n\tconst isSupportedMimeType = (mime: string): boolean => {\n\t\tconst mimeTypeArray = mime.split('/')\n\t\treturn splittedTypes.value.some(([type, subtype]) => (\n\t\t\t// check mime type matches or is wildcard\n\t\t\t(mimeTypeArray[0] === type || type === '*')\n\t\t\t// check mime subtype matches or is wildcard\n\t\t\t&& (mimeTypeArray[1] === subtype || subtype === '*')\n\t\t))\n\t}\n\n\treturn {\n\t\tisSupportedMimeType,\n\t}\n}\n","<!--\n  - SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors\n  - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n<template>\n\t<NcDialog\n\t\tv-model:open=\"isOpen\"\n\t\t:buttons=\"dialogButtons\"\n\t\t:name=\"name\"\n\t\tsize=\"large\"\n\t\tcontentClasses=\"file-picker__content\"\n\t\tdialogClasses=\"file-picker\"\n\t\tnavigationClasses=\"file-picker__navigation\"\n\t\t@update:open=\"handleClose\">\n\t\t<template #navigation=\"{ isCollapsed }\">\n\t\t\t<FilePickerNavigation\n\t\t\t\tv-model:currentView=\"currentView\"\n\t\t\t\tv-model:filterString=\"filterString\"\n\t\t\t\t:isCollapsed\n\t\t\t\t:disabledNavigation />\n\t\t</template>\n\n\t\t<div class=\"file-picker__main\">\n\t\t\t<!-- Header title / file list breadcrumbs -->\n\t\t\t<FilePickerBreadcrumbs\n\t\t\t\tv-if=\"currentView === 'files'\"\n\t\t\t\tv-model:path=\"currentPath\"\n\t\t\t\t:showMenu=\"!noMenu\"\n\t\t\t\t@createNode=\"onCreateFolder\" />\n\t\t\t<div v-else class=\"file-picker__view\">\n\t\t\t\t<h3>{{ viewHeadline }}</h3>\n\t\t\t</div>\n\n\t\t\t<!-- File list -->\n\t\t\t<!-- If loading or files found show file list, otherwise show empty content-->\n\t\t\t<FileList\n\t\t\t\tv-if=\"isLoading || filteredFiles.length > 0\"\n\t\t\t\tv-model:path=\"currentPath\"\n\t\t\t\tv-model:selectedFiles=\"selectedFiles\"\n\t\t\t\t:allowPickDirectory=\"allowPickDirectory\"\n\t\t\t\t:currentView=\"currentView\"\n\t\t\t\t:files=\"filteredFiles\"\n\t\t\t\t:multiselect=\"multiselect\"\n\t\t\t\t:loading=\"isLoading\"\n\t\t\t\t:name=\"viewHeadline\"\n\t\t\t\t:canPick=\"canPickFn\"\n\t\t\t\t@update:path=\"currentView = 'files'\" />\n\t\t\t<NcEmptyContent\n\t\t\t\tv-else-if=\"filterString\"\n\t\t\t\t:name=\"t('No matching files')\"\n\t\t\t\t:description=\"t('No files matching your filter were found.')\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<IconFile />\n\t\t\t\t</template>\n\t\t\t</NcEmptyContent>\n\t\t\t<NcEmptyContent\n\t\t\t\tv-else\n\t\t\t\t:name=\"t('No files in here')\"\n\t\t\t\t:description=\"noFilesDescription\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<IconFile />\n\t\t\t\t</template>\n\t\t\t</NcEmptyContent>\n\t\t</div>\n\t</NcDialog>\n</template>\n\n<script setup lang=\"ts\">\nimport type { INode } from '@nextcloud/files'\nimport type { IFilesViewId } from '../../composables/views.ts'\nimport type { IDialogButton, IFilePickerButton, IFilePickerButtonFactory, IFilePickerCanPick, IFilePickerFilter } from '../types.ts'\n\nimport { emit as emitOnEventBus } from '@nextcloud/event-bus'\nimport { computed, onMounted, ref, shallowRef, toRef, watch } from 'vue'\nimport NcDialog from '@nextcloud/vue/components/NcDialog'\nimport NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'\nimport IconFile from 'vue-material-design-icons/File.vue'\nimport FileList from './FileList.vue'\nimport FilePickerBreadcrumbs from './FilePickerBreadcrumbs.vue'\nimport FilePickerNavigation from './FilePickerNavigation.vue'\nimport { useDAVFiles } from '../../composables/dav.ts'\nimport { useFilesSettings } from '../../composables/filesSettings.ts'\nimport { useMimeFilter } from '../../composables/mime.ts'\nimport { showError } from '../../toast.ts'\nimport { t } from '../../utils/l10n.ts'\nimport { logger } from '../../utils/logger.ts'\n\nconst props = withDefaults(defineProps<{\n\t/** Buttons to be displayed */\n\tbuttons: IFilePickerButton[] | IFilePickerButtonFactory\n\n\t/** The name of file picker dialog (heading) */\n\tname: string\n\n\t/**\n\t * Can directories be picked\n\t *\n\t * @default false\n\t */\n\tallowPickDirectory?: boolean\n\n\t/**\n\t * Can new Files/folders be created\n\t *\n\t * @default false\n\t */\n\tnoMenu?: boolean\n\n\t/**\n\t * Is the navigation disabled\n\t */\n\tdisabledNavigation?: boolean\n\n\t/**\n\t * Custom filter function used to filter pickable files\n\t */\n\tfilterFn?: IFilePickerFilter\n\n\t/**\n\t * Custom function to decide if a node can be picked\n\t */\n\tcanPickFn?: IFilePickerCanPick\n\n\t/**\n\t * List of allowed mime types\n\t * You can use placeholders for e.g. allowing all subtypes of images `['image/*']`.\n\t * Note that if unset all files are allowed, which is the same as passing `['*∕*']`\n\t *\n\t * @default []\n\t */\n\tmimetypeFilter?: string[]\n\n\t/**\n\t * Is it allowed to pick multiple files\n\t */\n\tmultiselect?: boolean\n\n\t/**\n\t * The initial path of the file picker\n\t *\n\t * @default '/'\n\t */\n\tpath?: string\n}>(), {\n\tallowPickDirectory: false,\n\tnoMenu: false,\n\tdisabledNavigation: false,\n\tfilterFn: undefined,\n\tcanPickFn: undefined,\n\tmimetypeFilter: () => [],\n\tmultiselect: false,\n\tpath: undefined,\n})\n\nconst emit = defineEmits<{\n\t(e: 'close', v?: INode[]): void\n}>()\n\nconst isOpen = ref(true)\n\n/**\n * Name of the currently active view\n */\nconst currentView = ref<IFilesViewId>('files')\n\n/**\n * Last path navigated to using the file picker\n * (required as sessionStorage is not reactive)\n */\nconst savedPath = ref(window?.sessionStorage.getItem('NC.FilePicker.LastPath') || '/')\n\n/**\n * The path the user manually navigated to using this filepicker instance\n */\nconst navigatedPath = ref('')\n\n/**\n * The current path that should be picked from\n */\nconst currentPath = computed({\n\tget: () => {\n\t\t// Only use the path for the files view as favorites and recent only works on the root\n\t\treturn currentView.value === 'files' ? navigatedPath.value || props.path || savedPath.value : '/'\n\t},\n\tset: (path: string) => {\n\t\t// forward setting the current path to the navigated path\n\t\tnavigatedPath.value = path\n\t},\n})\n\n/**\n * All currently selected files\n */\nconst selectedFiles = shallowRef<INode[]>([])\n\nconst {\n\tfiles,\n\tfolder: currentFolder,\n\tisLoading,\n\tloadFiles,\n\tcreateDirectory,\n} = useDAVFiles(currentView, currentPath)\n\n// Save the navigated path to the session storage on change\nwatch([navigatedPath], () => {\n\tif (props.path === undefined && navigatedPath.value) {\n\t\twindow.sessionStorage.setItem('NC.FilePicker.LastPath', navigatedPath.value)\n\t}\n\t// Reset selected files\n\tselectedFiles.value = []\n})\n\n/**\n * Flag that is set when a button was clicked to prevent the default close event to be emitted\n * This is needed as `handleButtonClick` is async and thus might execute after NcDialog already closed\n */\nlet isHandlingCallback = false\n\n/**\n * Map buttons to Dialog buttons by wrapping the callback function to pass the selected files\n */\nconst dialogButtons = computed(() => {\n\tconst nodes = selectedFiles.value.length === 0\n\t\t&& props.allowPickDirectory\n\t\t&& currentFolder.value\n\t\t? [currentFolder.value]\n\t\t: selectedFiles.value\n\n\tconst buttons = typeof props.buttons === 'function'\n\t\t? props.buttons(nodes, currentPath.value, currentView.value)\n\t\t: props.buttons\n\n\treturn buttons.map((button) => ({\n\t\t...button,\n\t\tdisabled: button.disabled || isLoading.value,\n\t\tcallback: () => {\n\t\t\t// lock default close handling\n\t\t\tisHandlingCallback = true\n\t\t\thandleButtonClick(button.callback, nodes)\n\t\t},\n\t} satisfies IDialogButton))\n})\n\n/**\n * @param callback - Callback of the button\n * @param nodes - Currently selected nodes\n */\nasync function handleButtonClick(callback: IFilePickerButton['callback'], nodes: INode[]) {\n\tawait callback(nodes)\n\temit('close', nodes)\n\t// Unlock close\n\tisHandlingCallback = false\n}\n\n/**\n * Headline to be used on the current view\n */\nconst viewHeadline = computed(() => currentView.value === 'favorites' ? t('Favorites') : (currentView.value === 'recent' ? t('Recent') : ''))\n\n/**\n * A string used to filter files in current view\n */\nconst filterString = ref('')\n\nconst { isSupportedMimeType } = useMimeFilter(toRef(props, 'mimetypeFilter')) // vue 3.3 will allow cleaner syntax of toRef(() => props.mimetypeFilter)\n\nonMounted(() => loadFiles())\n\nconst { showHiddenFiles } = useFilesSettings()\n\n/**\n * The files list filtered by the current value of the filter input\n */\nconst filteredFiles = computed(() => {\n\tlet filtered = files.value\n\n\tif (!showHiddenFiles.value) {\n\t\t// Hide hidden files if not configured otherwise\n\t\tfiltered = filtered.filter((file) => !file.basename.startsWith('.'))\n\t}\n\tif (props.mimetypeFilter.length > 0) {\n\t\t// filter by mime type but always include folders to navigate\n\t\tfiltered = filtered.filter((file) => file.type === 'folder' || (file.mime && isSupportedMimeType(file.mime)))\n\t}\n\tif (filterString.value) {\n\t\tfiltered = filtered.filter((file) => file.basename.toLowerCase().includes(filterString.value.toLowerCase()))\n\t}\n\tif (props.filterFn) {\n\t\tfiltered = filtered.filter((f) => props.filterFn!(f as INode))\n\t}\n\treturn filtered\n})\n\n/**\n * If no files are found in the current view this message will be shown in the EmptyContent\n */\nconst noFilesDescription = computed(() => {\n\tif (currentView.value === 'files') {\n\t\treturn t('Upload some content or sync with your devices!')\n\t} else if (currentView.value === 'recent') {\n\t\treturn t('Files and folders you recently modified will show up here.')\n\t} else {\n\t\treturn t('Files and folders you mark as favorite will show up here.')\n\t}\n})\n\n/**\n * Handle creating new folder (breadcrumb menu)\n * This will create the folder using WebDAV, reload the directory content and signal the directory creation to fhe files app\n *\n * @param name The new folder name\n */\nasync function onCreateFolder(name: string) {\n\ttry {\n\t\tconst folder = await createDirectory(name)\n\t\tnavigatedPath.value = folder.path\n\t\t// emit event bus to force files app to reload that file if needed\n\t\temitOnEventBus('files:node:created', files.value.filter((file) => file.basename === name)[0])\n\t} catch (error) {\n\t\tlogger.warn('Could not create new folder', { name, error })\n\t\t// show error to user\n\t\tshowError(t('Could not create the new folder'))\n\t}\n}\n\n/**\n * Handle closing the file picker\n *\n * @param open If the dialog is open\n */\nfunction handleClose(open: boolean) {\n\tif (!open && !isHandlingCallback) {\n\t\temit('close')\n\t}\n}\n</script>\n\n<style scoped lang=\"scss\">\n.file-picker {\n\t&__view {\n\t\theight: 50px; // align with breadcrumbs\n\t\tdisplay: flex;\n\t\tjustify-content: start;\n\t\talign-items: center;\n\n\t\th3 {\n\t\t\tfont-weight: bold;\n\t\t\theight: fit-content;\n\t\t\tmargin: 0;\n\t\t}\n\t}\n\n\t&__main {\n\t\tbox-sizing: border-box;\n\t\twidth: 100%;\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t\t// Auto fit height\n\t\tmin-height: 0;\n\t\tflex: 1;\n\t\t// align with navigation on smaller screens\n\t\tpadding-inline: 2px;\n\n\t\t* {\n\t\t\tbox-sizing: border-box;\n\t\t}\n\t}\n}\n\n:deep(.file-picker) {\n\t// Dialog is max. 900px wide so the best looking height seems to be 800px\n\theight: min(80vh, 800px)!important;\n}\n\n@media (max-width: 512px) {\n\t:deep(.file-picker) {\n\t\t// below 512px the modal is fullscreen so we use 100% height - margin of heading (4px + 12px) - height of heading (default-clickable-area)\n\t\theight: calc(100% - 16px - var(--default-clickable-area))!important;\n\t}\n}\n\n:deep(.file-picker__content) {\n\tdisplay: flex;\n\tflex-direction: column;\n\toverflow: hidden;\n}\n</style>\n"],"names":["_sfc_main","_hoisted_3","_createElementBlock","_mergeProps","_createElementVNode","_openBlock","fileListIconStyles","fileListIconStylesModule","_normalizeStyle","_unref","_Fragment","_createBlock","_createVNode","emit","_toHandlers","_hoisted_2","FilePreview","_toDisplayString","_hoisted_6","_hoisted_7","_hoisted_1","_hoisted_4","order","_useModel","_createTextVNode","_renderList","_createSlots","$emit","emitOnEventBus","_withCtx"],"mappings":"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","x_google_ignoreList":[0,1,2,3,9,10,12,13]}