photos/js/photos-src_mixins_AbortCont...

1 line
112 KiB
XML

{"version":3,"file":"photos-src_mixins_AbortControllerMixin_js-src_mixins_FilesSelectionMixin_js-src_components_File_vue--80ca54.js?v=1629bbd306f50196435a","mappings":"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","sources":["webpack:///photos/src/components/FavoriteIcon.vue","webpack:///photos/src/components/File.vue","webpack://photos/./src/components/FavoriteIcon.vue?004d","webpack://photos/./src/components/File.vue?6403","webpack:///photos/src/mixins/AbortControllerMixin.js","webpack:///photos/src/mixins/FilesSelectionMixin.js","webpack:///photos/src/services/PreviewService.js","webpack:///photos/src/components/FavoriteIcon.vue?vue&type=style&index=0&id=a692ce86&prod&lang=scss&scoped=true","webpack:///photos/src/components/File.vue?vue&type=style&index=0&id=92e450b8&prod&lang=scss&scoped=true","webpack:///photos/src/components/FilesListViewer.vue?vue&type=style&index=0&id=53f8632c&prod&lang=scss&scoped=true","webpack:///photos/src/components/TiledLayout/TiledLayout.vue?vue&type=style&index=0&id=732189b2&prod&scoped=true&lang=scss","webpack:///photos/src/components/TiledLayout/TiledRows.vue?vue&type=style&index=0&id=c1815a46&prod&lang=scss&scoped=true","webpack:///photos/src/components/VirtualScrolling.vue?vue&type=style&index=0&id=50bb7c53&prod&scoped=true&lang=scss","webpack://photos/./src/components/FavoriteIcon.vue?c5d7","webpack://photos/./src/components/File.vue?47ed","webpack://photos/./src/components/FavoriteIcon.vue?0a4c","webpack://photos/./src/components/File.vue?f552","webpack://photos/./src/components/FilesListViewer.vue?033a","webpack:///photos/src/services/TiledLayout.js","webpack:///photos/src/components/TiledLayout/TiledRows.vue","webpack://photos/./src/components/TiledLayout/TiledRows.vue?7152","webpack://photos/./src/components/TiledLayout/TiledRows.vue?b628","webpack:///photos/src/components/TiledLayout/TiledLayout.vue?vue&type=script&lang=js","webpack:///photos/src/components/TiledLayout/TiledLayout.vue","webpack://photos/./src/components/TiledLayout/TiledLayout.vue?c73a","webpack://photos/./src/components/TiledLayout/TiledLayout.vue?5c93","webpack://photos/./src/components/TiledLayout/TiledLayout.vue?b933","webpack:///photos/src/services/fileFetcher.js","webpack:///photos/src/components/VirtualScrolling.vue","webpack:///photos/src/components/VirtualScrolling.vue?vue&type=script&lang=js","webpack://photos/./src/components/VirtualScrolling.vue?7ad4","webpack://photos/./src/components/VirtualScrolling.vue?6e3f","webpack://photos/./src/components/VirtualScrolling.vue?3e35","webpack:///photos/src/components/FilesListViewer.vue","webpack:///photos/src/components/FilesListViewer.vue?vue&type=script&lang=js","webpack://photos/./src/components/FilesListViewer.vue?b9b1","webpack://photos/./src/components/FilesListViewer.vue?5a4f","webpack:///photos/src/components/FavoriteIcon.vue?vue&type=script&lang=js","webpack:///photos/src/components/File.vue?vue&type=script&lang=js"],"sourcesContent":["<!--\n - @copyright Copyright (c) 2023 Ferdinand Thiessen <opensource@fthiessen.de>\n -\n - @author Ferdinand Thiessen <opensource@fthiessen.de>\n -\n - @license AGPL-3.0-or-later\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n<template>\n\t<NcIconSvgWrapper class=\"favorite-marker-icon\" :name=\"t('photos', 'Favorite')\" :svg=\"StarSvg\" />\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcIconSvgWrapper } from '@nextcloud/vue'\nimport { defineComponent } from 'vue'\n\n// eslint-disable-next-line import/no-unresolved, n/no-missing-import\nimport StarSvg from '@mdi/svg/svg/star.svg?raw'\n\n/**\n * A favorite icon to be used for overlaying favorite entries like the file preview / icon\n * It has a stroke around the star icon to ensure enough contrast for accessibility.\n *\n * If the background has a hover state you might want to also apply it to the stroke like this:\n * ```scss\n * .parent:hover :deep(.favorite-marker-icon svg path) {\n * stroke: var(--color-background-hover);\n * }\n * ```\n */\nexport default defineComponent({\n\tname: 'FavoriteIcon',\n\tcomponents: {\n\t\tNcIconSvgWrapper,\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tStarSvg,\n\t\t}\n\t},\n\tmounted() {\n\t\tthis.$nextTick(() => {\n\t\t\t// MDI default viewbox is \"0 0 24 24\" but we add a stroke of 10px so we must adjust it\n\t\t\tconst el = this.$el.querySelector('svg')\n\t\t\tel?.setAttribute?.('viewBox', '-4 -4 30 30')\n\t\t})\n\t},\n\tmethods: {\n\t\tt,\n\t},\n})\n</script>\n\n<style lang=\"scss\" scoped>\n.favorite-marker-icon {\n\tcolor: #a08b00;\n\t// Override NcIconSvgWrapper defaults (clickable area)\n\tmin-width: unset !important;\n\tmin-height: unset !important;\n\n\t:deep() {\n\t\tsvg {\n\t\t\t// We added a stroke for a11y so we must increase the size to include the stroke\n\t\t\twidth: 32px !important;\n\t\t\theight: 32px !important;\n\n\t\t\t// Override NcIconSvgWrapper defaults of 20px\n\t\t\tmax-width: unset !important;\n\t\t\tmax-height: unset !important;\n\n\t\t\t// Sow a border around the icon for better contrast\n\t\t\tpath {\n\t\t\t\tstroke: var(--color-main-background);\n\t\t\t\tstroke-width: 10px;\n\t\t\t\tstroke-linejoin: round;\n\t\t\t\tpaint-order: stroke;\n\t\t\t}\n\t\t}\n\t}\n}\n</style>\n","<!--\n - @copyright Copyright (c) 2020 Corentin Mors\n -\n - @license AGPL-3.0-or-later\n -\n - @author Corentin Mors <medias@pixelswap.fr>\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n\n<template>\n\t<div class=\"file-container\"\n\t\tdata-test=\"media\"\n\t\t:class=\"{selected}\">\n\t\t<a class=\"file\"\n\t\t\t:href=\"file.source\"\n\t\t\t:aria-label=\"ariaLabel\"\n\t\t\t@click.stop.prevent=\"emitClick\">\n\n\t\t\t<!-- image and loading placeholder -->\n\t\t\t<div class=\"file__images\">\n\t\t\t\t<VideoIcon v-if=\"file.mime.includes('video')\" class=\"icon-overlay\" :size=\"64\" />\n\t\t\t\t<PlayCircleIcon v-else-if=\"file.metadataFilesLivePhoto !== undefined\" class=\"icon-overlay\" :size=\"64\" />\n\n\t\t\t\t<!-- We have two img elements to load the small and large preview -->\n\t\t\t\t<!-- Do not show the small preview if the larger one is loaded -->\n\t\t\t\t<!-- Prioritize visible files -->\n\t\t\t\t<!-- Load small preview first, then the larger one -->\n\t\t\t\t<!-- Preload large preview for near visible files -->\n\t\t\t\t<!-- Preload small preview for further away files -->\n\t\t\t\t<template v-if=\"initialized\">\n\t\t\t\t\t<canvas v-if=\"hasBlurhash && !loadedSmall && !loadedLarge\" ref=\"canvas\" class=\"file__blurhash\" />\n\n\t\t\t\t\t<img v-if=\"!loadedLarge && (loadedSmall || (distance < 5 && !errorSmall))\"\n\t\t\t\t\t\tref=\"imgSmall\"\n\t\t\t\t\t\t:key=\"`${file.basename}-small`\"\n\t\t\t\t\t\t:src=\"srcSmall\"\n\t\t\t\t\t\t:alt=\"file.basename\"\n\t\t\t\t\t\t:decoding=\"loadedSmall || isVisible ? 'sync' : 'async'\"\n\t\t\t\t\t\t:fetchpriority=\"loadedSmall || isVisible ? 'high' : 'low'\"\n\t\t\t\t\t\t:loading=\"loadedSmall || isVisible ? 'eager' : distance < 2 ? 'auto' : 'lazy'\"\n\t\t\t\t\t\t@load=\"onLoadSmall\"\n\t\t\t\t\t\t@error=\"onErrorSmall\">\n\n\t\t\t\t\t<img v-if=\"loadedLarge || ((isVisible || (distance < 2 && (loadedSmall || errorSmall))) && !errorLarge)\"\n\t\t\t\t\t\tref=\"imgLarge\"\n\t\t\t\t\t\t:key=\"`${file.basename}-large`\"\n\t\t\t\t\t\t:src=\"srcLarge\"\n\t\t\t\t\t\t:alt=\"file.basename\"\n\t\t\t\t\t\t:decoding=\"loadedLarge || isVisible ? 'sync' : 'async'\"\n\t\t\t\t\t\t:fetchpriority=\"loadedLarge || isVisible ? 'high' : 'low'\"\n\t\t\t\t\t\t:loading=\"loadedLarge || isVisible ? 'auto' : 'lazy'\"\n\t\t\t\t\t\t@load=\"onLoadLarge\"\n\t\t\t\t\t\t@error=\"onErrorLarge\">\n\t\t\t\t</template>\n\t\t\t</div>\n\t\t</a>\n\n\t\t<NcCheckboxRadioSwitch v-if=\"allowSelection\"\n\t\t\tclass=\"selection-checkbox\"\n\t\t\t:aria-label=\"t('photos', 'Select image {imageName}', {imageName: file.basename})\"\n\t\t\t:checked=\"selected\"\n\t\t\t@update:checked=\"onToggle\" />\n\n\t\t<FavoriteIcon v-if=\"file.favorite === 1\"\n\t\t\tv-once\n\t\t\tclass=\"favorite-state\" />\n\t</div>\n</template>\n\n<script>\nimport VideoIcon from 'vue-material-design-icons/Video.vue'\nimport PlayCircleIcon from 'vue-material-design-icons/PlayCircle.vue'\nimport { decode } from 'blurhash'\n\nimport { generateUrl } from '@nextcloud/router'\nimport { NcCheckboxRadioSwitch } from '@nextcloud/vue'\n\nimport FavoriteIcon from './FavoriteIcon.vue'\nimport { isCachedPreview } from '../services/PreviewService.js'\n\nexport default {\n\tname: 'File',\n\tcomponents: {\n\t\tFavoriteIcon,\n\t\tNcCheckboxRadioSwitch,\n\t\tVideoIcon,\n\t\tPlayCircleIcon,\n\t},\n\tinheritAttrs: false,\n\tprops: {\n\t\tfile: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t\tallowSelection: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t\tdistance: {\n\t\t\ttype: Number,\n\t\t\tdefault: 0,\n\t\t},\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tinitialized: false,\n\t\t\tloadedSmall: false,\n\t\t\terrorSmall: false,\n\t\t\tloadedLarge: false,\n\t\t\terrorLarge: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} */\n\t\tariaLabel() {\n\t\t\tif (this.file.favorite) {\n\t\t\t\treturn t('photos', 'Favorite image, open the full size \"{name}\" image', { name: this.file.basename })\n\t\t\t}\n\t\t\treturn t('photos', 'Open the full size \"{name}\" image', { name: this.file.basename })\n\t\t},\n\t\t/** @return {boolean} */\n\t\tisImage() {\n\t\t\treturn this.file.mime.startsWith('image')\n\t\t},\n\t\t/** @return {string} */\n\t\tdecodedEtag() {\n\t\t\treturn this.file.etag.replace('&quot;', '').replace('&quot;', '')\n\t\t},\n\t\t/** @return {string} */\n\t\tsrcLarge() {\n\t\t\treturn this.getItemURL(512)\n\t\t},\n\t\t/** @return {string} */\n\t\tsrcSmall() {\n\t\t\treturn this.getItemURL(64)\n\t\t},\n\t\t/** @return {boolean} */\n\t\tisVisible() {\n\t\t\treturn this.distance === 0\n\t\t},\n\t\thasBlurhash() {\n\t\t\treturn this.file.metadataBlurhash !== undefined\n\t\t},\n\t},\n\n\twatch: {\n\t\tfile() {\n\t\t\tthis.initialized = false\n\t\t\tthis.loadedSmall = false\n\t\t\tthis.errorSmall = false\n\t\t\tthis.loadedLarge = false\n\t\t\tthis.errorLarge = false\n\t\t},\n\t},\n\n\tasync mounted() {\n\t\t[this.loadedSmall, this.loadedLarge] = await Promise.all([\n\t\t\tawait isCachedPreview(this.srcSmall),\n\t\t\tawait isCachedPreview(this.srcLarge),\n\t\t])\n\n\t\tthis.initialized = true\n\n\t\tawait this.$nextTick() // Wait for next tick to have the canvas in the DOM\n\n\t\tthis.drawBlurhash()\n\t},\n\n\tbeforeDestroy() {\n\t\t// cancel any pending load\n\t\tif (this.$refs.imgSmall !== undefined) {\n\t\t\tthis.$refs.imgSmall.src = ''\n\t\t}\n\t\tif (this.$refs.srcLarge !== undefined) {\n\t\t\tthis.$refs.srcLarge.src = ''\n\t\t}\n\t},\n\n\tmethods: {\n\t\temitClick() {\n\t\t\tthis.$emit('click', this.file.fileid)\n\t\t},\n\n\t\tonLoadSmall() {\n\t\t\tthis.loadedSmall = true\n\t\t},\n\n\t\tonLoadLarge() {\n\t\t\tthis.loadedLarge = true\n\t\t},\n\n\t\tonErrorSmall() {\n\t\t\tthis.errorSmall = true\n\t\t},\n\n\t\tonErrorLarge() {\n\t\t\tthis.errorLarge = true\n\t\t},\n\n\t\tonToggle(value) {\n\t\t\tthis.$emit('select-toggled', { id: this.file.fileid, value })\n\t\t},\n\n\t\tgetItemURL(size) {\n\t\t\tconst token = this.$route?.params.token\n\t\t\tif (token) {\n\t\t\t\treturn generateUrl(`/apps/photos/api/v1/publicPreview/${this.file.fileid}?etag=${this.decodedEtag}&x=${size}&y=${size}&token=${token}`)\n\t\t\t} else {\n\t\t\t\treturn generateUrl(`/apps/photos/api/v1/preview/${this.file.fileid}?etag=${this.decodedEtag}&x=${size}&y=${size}`)\n\t\t\t}\n\t\t},\n\t\tdrawBlurhash() {\n\t\t\tif (!this.hasBlurhash || !this.$refs.canvas) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst width = this.$refs.canvas.width\n\t\t\tconst height = this.$refs.canvas.height\n\n\t\t\tconst pixels = decode(this.file.metadataBlurhash, width, height)\n\n\t\t\tconst ctx = this.$refs.canvas.getContext('2d')\n\t\t\tconst imageData = ctx.createImageData(width, height)\n\t\t\timageData.data.set(pixels)\n\t\t\tctx.putImageData(imageData, 0, 0)\n\t\t},\n\t},\n\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.file-container {\n\tcontain: strict;\n\tbackground: var(--color-primary-element-light);\n\tposition: relative;\n\theight: 100%;\n\twidth: 100%;\n\tborder: 2px solid var(--color-main-background); // Use border so create a separation between images.\n\tbox-sizing: border-box;\n\n\t// Selection border.\n\t&.selected,\n\t&:focus-within,\n\t&:has(:focus) {\n\t\t&::after {\n\t\t\tposition: absolute;\n\t\t\ttop: 0;\n\t\t\tleft: 0;\n\t\t\tz-index: 2;\n\t\t\twidth: 100%;\n\t\t\theight: 100%;\n\t\t\tcontent: '';\n\t\t\toutline: var(--color-primary-element) solid 4px;\n\t\t\toutline-offset: -4px;\n\t\t\tpointer-events: none;\n\t\t}\n\n\t\t.selection-checkbox {\n\t\t\topacity: 1;\n\t\t}\n\t}\n\n\t.file {\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tbox-sizing: border-box;\n\t\toutline: none; // Override global focus state.\n\t\tdisplay: flex; // Fill parent size\n\n\t\t&__blurhash {\n\t\t\tposition: absolute;\n\t\t\ttop: 0;\n\t\t\theight: 100%;\n\t\t\twidth: 100%;\n\t\t\tobject-fit: cover;\n\t\t}\n\n\t\t&__images {\n\t\t\twidth: 100%;\n\t\t\theight: 100%;\n\n\t\t\t.icon-overlay {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 0px;\n\t\t\t\tright: 0px;\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 100%;\n\t\t\t\tz-index: 1;\n\t\t\t\topacity: 0.8;\n\n\t\t\t\t:deep .material-design-icon__svg {\n\t\t\t\t\tfill: var(--color-main-background);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\timg {\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 100%;\n\t\t\t\tobject-fit: cover;\n\t\t\t\tposition: absolute;\n\t\t\t\tcolor: transparent; /// Hide alt='' text when loading.\n\t\t\t}\n\t\t}\n\t}\n\n\t// Reveal checkbox on hover.\n\t&:hover, &.selected, &:focus-within {\n\t\t.selection-checkbox {\n\t\t\topacity: 1;\n\t\t}\n\n\t\t.favorite-state {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n\n\t.selection-checkbox {\n\t\topacity: 0;\n\t\tposition: absolute;\n\t\ttop: 8px;\n\t\t// Fancy calculation to render the checkbox in the middle of narrow images.\n\t\tright: min(22px, calc(50% - 7px));\n\t\tz-index: 1;\n\t\twidth: fit-content;\n\n\t\t:deep .checkbox-radio-switch__input:focus-visible + .checkbox-radio-switch__content,\n\t\t.checkbox-radio-switch__input:focus-visible {\n\t\t\toutline: 2px solid var(--color-main-text);\n\t\t\tbox-shadow: 0 0 0 3px var(--color-main-background);\n\t\t\toutline-offset: 0px;\n\t\t}\n\n\t\t:deep .checkbox-radio-switch__content {\n\t\t\tpadding: 10px;\n\t\t\tbox-sizing: border-box;\n\t\t\tbackground: var(--color-main-background);\n\n\t\t\t// Add a background to the checkbox so we do not see the image through it.\n\t\t\t&::after {\n\t\t\t\tcontent: '';\n\t\t\t\twidth: 16px;\n\t\t\t\theight: 16px;\n\t\t\t\tposition: absolute;\n\t\t\t\tleft: 14px;\n\t\t\t\tz-index: -1;\n\t\t\t}\n\n\t\t\t.checkbox-radio-switch__icon {\n\t\t\t\tmargin: 0;\n\t\t\t}\n\t\t}\n\n\t\t.input-label {\n\t\t\tposition: fixed;\n\t\t\tz-index: -1;\n\t\t\ttop: -5000px;\n\t\t\tleft: -5000px;\n\t\t}\n\t}\n\n\t.favorite-state {\n\t\tposition: absolute;\n\t\ttop: 2px;\n\t\t// Fancy calculation to render the start in the middle of narrow images.\n\t\tright: min(2px, calc(50% - 7px));\n\t}\n}\n</style>\n","var render = function render(){var _vm=this,_c=_vm._self._c,_setup=_vm._self._setupProxy;return _c('NcIconSvgWrapper',{staticClass:\"favorite-marker-icon\",attrs:{\"name\":_vm.t('photos', 'Favorite'),\"svg\":_vm.StarSvg}})\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"file-container\",class:{selected: _vm.selected},attrs:{\"data-test\":\"media\"}},[_c('a',{staticClass:\"file\",attrs:{\"href\":_vm.file.source,\"aria-label\":_vm.ariaLabel},on:{\"click\":function($event){$event.stopPropagation();$event.preventDefault();return _vm.emitClick.apply(null, arguments)}}},[_c('div',{staticClass:\"file__images\"},[(_vm.file.mime.includes('video'))?_c('VideoIcon',{staticClass:\"icon-overlay\",attrs:{\"size\":64}}):(_vm.file.metadataFilesLivePhoto !== undefined)?_c('PlayCircleIcon',{staticClass:\"icon-overlay\",attrs:{\"size\":64}}):_vm._e(),_vm._v(\" \"),(_vm.initialized)?[(_vm.hasBlurhash && !_vm.loadedSmall && !_vm.loadedLarge)?_c('canvas',{ref:\"canvas\",staticClass:\"file__blurhash\"}):_vm._e(),_vm._v(\" \"),(!_vm.loadedLarge && (_vm.loadedSmall || (_vm.distance < 5 && !_vm.errorSmall)))?_c('img',{key:`${_vm.file.basename}-small`,ref:\"imgSmall\",attrs:{\"src\":_vm.srcSmall,\"alt\":_vm.file.basename,\"decoding\":_vm.loadedSmall || _vm.isVisible ? 'sync' : 'async',\"fetchpriority\":_vm.loadedSmall || _vm.isVisible ? 'high' : 'low',\"loading\":_vm.loadedSmall || _vm.isVisible ? 'eager' : _vm.distance < 2 ? 'auto' : 'lazy'},on:{\"load\":_vm.onLoadSmall,\"error\":_vm.onErrorSmall}}):_vm._e(),_vm._v(\" \"),(_vm.loadedLarge || ((_vm.isVisible || (_vm.distance < 2 && (_vm.loadedSmall || _vm.errorSmall))) && !_vm.errorLarge))?_c('img',{key:`${_vm.file.basename}-large`,ref:\"imgLarge\",attrs:{\"src\":_vm.srcLarge,\"alt\":_vm.file.basename,\"decoding\":_vm.loadedLarge || _vm.isVisible ? 'sync' : 'async',\"fetchpriority\":_vm.loadedLarge || _vm.isVisible ? 'high' : 'low',\"loading\":_vm.loadedLarge || _vm.isVisible ? 'auto' : 'lazy'},on:{\"load\":_vm.onLoadLarge,\"error\":_vm.onErrorLarge}}):_vm._e()]:_vm._e()],2)]),_vm._v(\" \"),(_vm.allowSelection)?_c('NcCheckboxRadioSwitch',{staticClass:\"selection-checkbox\",attrs:{\"aria-label\":_vm.t('photos', 'Select image {imageName}', {imageName: _vm.file.basename}),\"checked\":_vm.selected},on:{\"update:checked\":_vm.onToggle}}):_vm._e(),_vm._v(\" \"),(_vm.file.favorite === 1)?_vm._m(0):_vm._e()],1)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('FavoriteIcon',{staticClass:\"favorite-state\"})\n}]\n\nexport { render, staticRenderFns }","/**\n * @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>\n *\n * @author Louis Chemineau <louis@chmn.me>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nexport default {\n\tname: 'AbortControllerMixin',\n\n\tdata() {\n\t\treturn {\n\t\t\tabortController: new AbortController(),\n\t\t}\n\t},\n\n\tbeforeDestroy() {\n\t\tthis.abortController.abort()\n\t},\n\n\tbeforeRouteLeave(from, to, next) {\n\t\tthis.abortController.abort()\n\t\tthis.abortController = new AbortController()\n\t\tnext()\n\t},\n}\n","/**\n * @copyright Copyright (c) 2019 Louis Chemineau <louis@chmn.me>\n *\n * @author Louis Chemineau <louis@chmn.me>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nexport default {\n\tname: 'FilesSelectionMixin',\n\n\tdata() {\n\t\treturn {\n\t\t\t/** @type {Object<string, boolean>} */\n\t\t\tselection: {},\n\t\t}\n\t},\n\n\twatch: {\n\t\t$route() {\n\t\t\tthis.resetSelection()\n\t\t},\n\t},\n\n\tmethods: {\n\t\tonFileSelectToggle({ id, value }) {\n\t\t\tthis.$set(this.selection, id, value)\n\t\t},\n\n\t\t/**\n\t\t * @param {string[]} filesIds - The ids of the files to uncheck.\n\t\t */\n\t\tonUncheckFiles(filesIds) {\n\t\t\tfilesIds.forEach((/** @type {string} */ filesId) => this.$set(this.selection, filesId, false))\n\t\t},\n\n\t\tresetSelection() {\n\t\t\tthis.selection = {}\n\t\t},\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * @return {string[]}\n\t\t */\n\t\tselectedFileIds() {\n\t\t\treturn Object.keys(this.selection).filter(fileId => this.selection[fileId])\n\t\t},\n\t},\n}\n","/**\n * @copyright Copyright (c) 2023 Louis Chmn <louis@chmn.me>\n *\n * @author Louis Chmn <louis@chmn.me>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\n// The preview service worker cache name (see webpack config)\nconst SWCacheName = 'images'\nconst hotCache = []\n/**\n * Check if the preview is already cached by the service worker\n *\n * @param {string} previewUrl - The URL of the preview to check\n * @return {Promise<boolean>}\n */\nexport const isCachedPreview = async function(previewUrl) {\n\ttry {\n\t\t// Browser's cache take ~100ms to check, hot cache ~10ms.\n\t\tif (!hotCache[previewUrl]) {\n\t\t\tconst cache = await window.caches?.open(SWCacheName)\n\t\t\tconst response = await cache?.match(previewUrl)\n\t\t\thotCache[previewUrl] = response !== undefined\n\t\t}\n\n\t\treturn hotCache[previewUrl]\n\t} catch {\n\t\treturn false\n\t}\n}\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".favorite-marker-icon[data-v-a692ce86]{color:#a08b00;min-width:unset !important;min-height:unset !important}.favorite-marker-icon[data-v-a692ce86] svg{width:32px !important;height:32px !important;max-width:unset !important;max-height:unset !important}.favorite-marker-icon[data-v-a692ce86] svg path{stroke:var(--color-main-background);stroke-width:10px;stroke-linejoin:round;paint-order:stroke}\", \"\",{\"version\":3,\"sources\":[\"webpack://./src/components/FavoriteIcon.vue\"],\"names\":[],\"mappings\":\"AAEA,uCACC,aAAA,CAEA,0BAAA,CACA,2BAAA,CAGC,4CAEC,qBAAA,CACA,sBAAA,CAGA,0BAAA,CACA,2BAAA,CAGA,iDACC,mCAAA,CACA,iBAAA,CACA,qBAAA,CACA,kBAAA\",\"sourcesContent\":[\"$sizes: (\\\"400\\\": (\\\"count\\\": 3, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"700\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"1024\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1280\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1440\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"1600\\\": (\\\"count\\\": 6, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2048\\\": (\\\"count\\\": 7, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2560\\\": (\\\"count\\\": 8, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"3440\\\": (\\\"count\\\": 9, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"max\\\": (\\\"count\\\": 10, \\\"marginTop\\\": 88, \\\"marginW\\\": 88));\\n\\n.favorite-marker-icon {\\n\\tcolor: #a08b00;\\n\\t// Override NcIconSvgWrapper defaults (clickable area)\\n\\tmin-width: unset !important;\\n\\tmin-height: unset !important;\\n\\n\\t:deep() {\\n\\t\\tsvg {\\n\\t\\t\\t// We added a stroke for a11y so we must increase the size to include the stroke\\n\\t\\t\\twidth: 32px !important;\\n\\t\\t\\theight: 32px !important;\\n\\n\\t\\t\\t// Override NcIconSvgWrapper defaults of 20px\\n\\t\\t\\tmax-width: unset !important;\\n\\t\\t\\tmax-height: unset !important;\\n\\n\\t\\t\\t// Sow a border around the icon for better contrast\\n\\t\\t\\tpath {\\n\\t\\t\\t\\tstroke: var(--color-main-background);\\n\\t\\t\\t\\tstroke-width: 10px;\\n\\t\\t\\t\\tstroke-linejoin: round;\\n\\t\\t\\t\\tpaint-order: stroke;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".file-container[data-v-92e450b8]{contain:strict;background:var(--color-primary-element-light);position:relative;height:100%;width:100%;border:2px solid var(--color-main-background);box-sizing:border-box}.file-container.selected[data-v-92e450b8]::after,.file-container[data-v-92e450b8]:focus-within::after,.file-container[data-v-92e450b8]:has(:focus)::after{position:absolute;top:0;left:0;z-index:2;width:100%;height:100%;content:\\\"\\\";outline:var(--color-primary-element) solid 4px;outline-offset:-4px;pointer-events:none}.file-container.selected .selection-checkbox[data-v-92e450b8],.file-container:focus-within .selection-checkbox[data-v-92e450b8],.file-container:has(:focus) .selection-checkbox[data-v-92e450b8]{opacity:1}.file-container .file[data-v-92e450b8]{width:100%;height:100%;box-sizing:border-box;outline:none;display:flex}.file-container .file__blurhash[data-v-92e450b8]{position:absolute;top:0;height:100%;width:100%;object-fit:cover}.file-container .file__images[data-v-92e450b8]{width:100%;height:100%}.file-container .file__images .icon-overlay[data-v-92e450b8]{position:absolute;top:0px;right:0px;width:100%;height:100%;z-index:1;opacity:.8}.file-container .file__images .icon-overlay[data-v-92e450b8] .material-design-icon__svg{fill:var(--color-main-background)}.file-container .file__images img[data-v-92e450b8]{width:100%;height:100%;object-fit:cover;position:absolute;color:rgba(0,0,0,0)}.file-container:hover .selection-checkbox[data-v-92e450b8],.file-container.selected .selection-checkbox[data-v-92e450b8],.file-container:focus-within .selection-checkbox[data-v-92e450b8]{opacity:1}.file-container:hover .favorite-state[data-v-92e450b8],.file-container.selected .favorite-state[data-v-92e450b8],.file-container:focus-within .favorite-state[data-v-92e450b8]{display:none}.file-container .selection-checkbox[data-v-92e450b8]{opacity:0;position:absolute;top:8px;right:min(22px,50% - 7px);z-index:1;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.file-container .selection-checkbox[data-v-92e450b8] .checkbox-radio-switch__input:focus-visible+.checkbox-radio-switch__content,.file-container .selection-checkbox .checkbox-radio-switch__input[data-v-92e450b8]:focus-visible{outline:2px solid var(--color-main-text);box-shadow:0 0 0 3px var(--color-main-background);outline-offset:0px}.file-container .selection-checkbox[data-v-92e450b8] .checkbox-radio-switch__content{padding:10px;box-sizing:border-box;background:var(--color-main-background)}.file-container .selection-checkbox[data-v-92e450b8] .checkbox-radio-switch__content::after{content:\\\"\\\";width:16px;height:16px;position:absolute;left:14px;z-index:-1}.file-container .selection-checkbox[data-v-92e450b8] .checkbox-radio-switch__content .checkbox-radio-switch__icon{margin:0}.file-container .selection-checkbox .input-label[data-v-92e450b8]{position:fixed;z-index:-1;top:-5000px;left:-5000px}.file-container .favorite-state[data-v-92e450b8]{position:absolute;top:2px;right:min(2px,50% - 7px)}\", \"\",{\"version\":3,\"sources\":[\"webpack://./src/components/File.vue\"],\"names\":[],\"mappings\":\"AAEA,iCACC,cAAA,CACA,6CAAA,CACA,iBAAA,CACA,WAAA,CACA,UAAA,CACA,6CAAA,CACA,qBAAA,CAMC,0JACC,iBAAA,CACA,KAAA,CACA,MAAA,CACA,SAAA,CACA,UAAA,CACA,WAAA,CACA,UAAA,CACA,8CAAA,CACA,mBAAA,CACA,mBAAA,CAGD,iMACC,SAAA,CAIF,uCACC,UAAA,CACA,WAAA,CACA,qBAAA,CACA,YAAA,CACA,YAAA,CAEA,iDACC,iBAAA,CACA,KAAA,CACA,WAAA,CACA,UAAA,CACA,gBAAA,CAGD,+CACC,UAAA,CACA,WAAA,CAEA,6DACC,iBAAA,CACA,OAAA,CACA,SAAA,CACA,UAAA,CACA,WAAA,CACA,SAAA,CACA,UAAA,CAEA,wFACC,iCAAA,CAIF,mDACC,UAAA,CACA,WAAA,CACA,gBAAA,CACA,iBAAA,CACA,mBAAA,CAOF,2LACC,SAAA,CAGD,+KACC,YAAA,CAIF,qDACC,SAAA,CACA,iBAAA,CACA,OAAA,CAEA,yBAAA,CACA,SAAA,CACA,yBAAA,CAAA,sBAAA,CAAA,iBAAA,CAEA,kOAEC,wCAAA,CACA,iDAAA,CACA,kBAAA,CAGD,qFACC,YAAA,CACA,qBAAA,CACA,uCAAA,CAGA,4FACC,UAAA,CACA,UAAA,CACA,WAAA,CACA,iBAAA,CACA,SAAA,CACA,UAAA,CAGD,kHACC,QAAA,CAIF,kEACC,cAAA,CACA,UAAA,CACA,WAAA,CACA,YAAA,CAIF,iDACC,iBAAA,CACA,OAAA,CAEA,wBAAA\",\"sourcesContent\":[\"$sizes: (\\\"400\\\": (\\\"count\\\": 3, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"700\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"1024\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1280\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1440\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"1600\\\": (\\\"count\\\": 6, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2048\\\": (\\\"count\\\": 7, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2560\\\": (\\\"count\\\": 8, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"3440\\\": (\\\"count\\\": 9, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"max\\\": (\\\"count\\\": 10, \\\"marginTop\\\": 88, \\\"marginW\\\": 88));\\n\\n.file-container {\\n\\tcontain: strict;\\n\\tbackground: var(--color-primary-element-light);\\n\\tposition: relative;\\n\\theight: 100%;\\n\\twidth: 100%;\\n\\tborder: 2px solid var(--color-main-background); // Use border so create a separation between images.\\n\\tbox-sizing: border-box;\\n\\n\\t// Selection border.\\n\\t&.selected,\\n\\t&:focus-within,\\n\\t&:has(:focus) {\\n\\t\\t&::after {\\n\\t\\t\\tposition: absolute;\\n\\t\\t\\ttop: 0;\\n\\t\\t\\tleft: 0;\\n\\t\\t\\tz-index: 2;\\n\\t\\t\\twidth: 100%;\\n\\t\\t\\theight: 100%;\\n\\t\\t\\tcontent: '';\\n\\t\\t\\toutline: var(--color-primary-element) solid 4px;\\n\\t\\t\\toutline-offset: -4px;\\n\\t\\t\\tpointer-events: none;\\n\\t\\t}\\n\\n\\t\\t.selection-checkbox {\\n\\t\\t\\topacity: 1;\\n\\t\\t}\\n\\t}\\n\\n\\t.file {\\n\\t\\twidth: 100%;\\n\\t\\theight: 100%;\\n\\t\\tbox-sizing: border-box;\\n\\t\\toutline: none; // Override global focus state.\\n\\t\\tdisplay: flex; // Fill parent size\\n\\n\\t\\t&__blurhash {\\n\\t\\t\\tposition: absolute;\\n\\t\\t\\ttop: 0;\\n\\t\\t\\theight: 100%;\\n\\t\\t\\twidth: 100%;\\n\\t\\t\\tobject-fit: cover;\\n\\t\\t}\\n\\n\\t\\t&__images {\\n\\t\\t\\twidth: 100%;\\n\\t\\t\\theight: 100%;\\n\\n\\t\\t\\t.icon-overlay {\\n\\t\\t\\t\\tposition: absolute;\\n\\t\\t\\t\\ttop: 0px;\\n\\t\\t\\t\\tright: 0px;\\n\\t\\t\\t\\twidth: 100%;\\n\\t\\t\\t\\theight: 100%;\\n\\t\\t\\t\\tz-index: 1;\\n\\t\\t\\t\\topacity: 0.8;\\n\\n\\t\\t\\t\\t:deep .material-design-icon__svg {\\n\\t\\t\\t\\t\\tfill: var(--color-main-background);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\n\\t\\t\\timg {\\n\\t\\t\\t\\twidth: 100%;\\n\\t\\t\\t\\theight: 100%;\\n\\t\\t\\t\\tobject-fit: cover;\\n\\t\\t\\t\\tposition: absolute;\\n\\t\\t\\t\\tcolor: transparent; /// Hide alt='' text when loading.\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\n\\t// Reveal checkbox on hover.\\n\\t&:hover, &.selected, &:focus-within {\\n\\t\\t.selection-checkbox {\\n\\t\\t\\topacity: 1;\\n\\t\\t}\\n\\n\\t\\t.favorite-state {\\n\\t\\t\\tdisplay: none;\\n\\t\\t}\\n\\t}\\n\\n\\t.selection-checkbox {\\n\\t\\topacity: 0;\\n\\t\\tposition: absolute;\\n\\t\\ttop: 8px;\\n\\t\\t// Fancy calculation to render the checkbox in the middle of narrow images.\\n\\t\\tright: min(22px, calc(50% - 7px));\\n\\t\\tz-index: 1;\\n\\t\\twidth: fit-content;\\n\\n\\t\\t:deep .checkbox-radio-switch__input:focus-visible + .checkbox-radio-switch__content,\\n\\t\\t.checkbox-radio-switch__input:focus-visible {\\n\\t\\t\\toutline: 2px solid var(--color-main-text);\\n\\t\\t\\tbox-shadow: 0 0 0 3px var(--color-main-background);\\n\\t\\t\\toutline-offset: 0px;\\n\\t\\t}\\n\\n\\t\\t:deep .checkbox-radio-switch__content {\\n\\t\\t\\tpadding: 10px;\\n\\t\\t\\tbox-sizing: border-box;\\n\\t\\t\\tbackground: var(--color-main-background);\\n\\n\\t\\t\\t// Add a background to the checkbox so we do not see the image through it.\\n\\t\\t\\t&::after {\\n\\t\\t\\t\\tcontent: '';\\n\\t\\t\\t\\twidth: 16px;\\n\\t\\t\\t\\theight: 16px;\\n\\t\\t\\t\\tposition: absolute;\\n\\t\\t\\t\\tleft: 14px;\\n\\t\\t\\t\\tz-index: -1;\\n\\t\\t\\t}\\n\\n\\t\\t\\t.checkbox-radio-switch__icon {\\n\\t\\t\\t\\tmargin: 0;\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\t.input-label {\\n\\t\\t\\tposition: fixed;\\n\\t\\t\\tz-index: -1;\\n\\t\\t\\ttop: -5000px;\\n\\t\\t\\tleft: -5000px;\\n\\t\\t}\\n\\t}\\n\\n\\t.favorite-state {\\n\\t\\tposition: absolute;\\n\\t\\ttop: 2px;\\n\\t\\t// Fancy calculation to render the start in the middle of narrow images.\\n\\t\\tright: min(2px, calc(50% - 7px));\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".files-list-viewer[data-v-53f8632c]{height:100%;position:relative}.files-list-viewer__placeholder[data-v-53f8632c]{background:var(--color-primary-element-light);width:100%;height:100%;border:2px solid var(--color-main-background)}.files-list-viewer .tiled-container[data-v-53f8632c]{flex-basis:0}.files-list-viewer ul[data-v-53f8632c]{display:flex;flex-wrap:wrap}.files-list-viewer ul li[data-v-53f8632c]:not(.last-tiled-rows){flex-grow:1}.files-list-viewer__section-header[data-v-53f8632c]{position:-webkit-sticky;position:sticky;top:0;z-index:3;background:var(--color-main-background)}.files-list-viewer__loader[data-v-53f8632c]{margin:50px 0}\", \"\",{\"version\":3,\"sources\":[\"webpack://./src/components/FilesListViewer.vue\"],\"names\":[],\"mappings\":\"AAEA,oCACC,WAAA,CACA,iBAAA,CAEA,iDACC,6CAAA,CACA,UAAA,CACA,WAAA,CACA,6CAAA,CAGD,qDACC,YAAA,CAGD,uCACC,YAAA,CACA,cAAA,CAEA,gEACC,WAAA,CAIF,oDACC,uBAAA,CAAA,eAAA,CACA,KAAA,CACA,SAAA,CACA,uCAAA,CAGD,4CACC,aAAA\",\"sourcesContent\":[\"$sizes: (\\\"400\\\": (\\\"count\\\": 3, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"700\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"1024\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1280\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1440\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"1600\\\": (\\\"count\\\": 6, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2048\\\": (\\\"count\\\": 7, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2560\\\": (\\\"count\\\": 8, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"3440\\\": (\\\"count\\\": 9, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"max\\\": (\\\"count\\\": 10, \\\"marginTop\\\": 88, \\\"marginW\\\": 88));\\n\\n.files-list-viewer {\\n\\theight: 100%;\\n\\tposition: relative;\\n\\n\\t&__placeholder {\\n\\t\\tbackground: var(--color-primary-element-light);\\n\\t\\twidth: 100%;\\n\\t\\theight: 100%;\\n\\t\\tborder: 2px solid var(--color-main-background); // Use border so create a separation between images.\\n\\t}\\n\\n\\t.tiled-container {\\n\\t\\tflex-basis: 0;\\n\\t}\\n\\n\\tul {\\n\\t\\tdisplay: flex;\\n\\t\\tflex-wrap: wrap;\\n\\n\\t\\tli:not(.last-tiled-rows) {\\n\\t\\t\\tflex-grow: 1;\\n\\t\\t}\\n\\t}\\n\\n\\t&__section-header {\\n\\t\\tposition: sticky;\\n\\t\\ttop: 0;\\n\\t\\tz-index: 3;\\n\\t\\tbackground: var(--color-main-background);\\n\\t}\\n\\n\\t&__loader {\\n\\t\\tmargin: 50px 0;\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".tiled-container[data-v-732189b2]{height:100%}.tiled-container .tiled-row[data-v-732189b2]{display:flex}\", \"\",{\"version\":3,\"sources\":[\"webpack://./src/components/TiledLayout/TiledLayout.vue\"],\"names\":[],\"mappings\":\"AAEA,kCACC,WAAA,CAEA,6CACC,YAAA\",\"sourcesContent\":[\"$sizes: (\\\"400\\\": (\\\"count\\\": 3, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"700\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"1024\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1280\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1440\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"1600\\\": (\\\"count\\\": 6, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2048\\\": (\\\"count\\\": 7, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2560\\\": (\\\"count\\\": 8, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"3440\\\": (\\\"count\\\": 9, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"max\\\": (\\\"count\\\": 10, \\\"marginTop\\\": 88, \\\"marginW\\\": 88));\\n\\n.tiled-container {\\n\\theight: 100%;\\n\\n\\t.tiled-row {\\n\\t\\tdisplay: flex;\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".tiled-row[data-v-c1815a46]{display:flex}\", \"\",{\"version\":3,\"sources\":[\"webpack://./src/components/TiledLayout/TiledRows.vue\"],\"names\":[],\"mappings\":\"AAEA,4BACC,YAAA\",\"sourcesContent\":[\"$sizes: (\\\"400\\\": (\\\"count\\\": 3, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"700\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"1024\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1280\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1440\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"1600\\\": (\\\"count\\\": 6, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2048\\\": (\\\"count\\\": 7, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2560\\\": (\\\"count\\\": 8, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"3440\\\": (\\\"count\\\": 9, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"max\\\": (\\\"count\\\": 10, \\\"marginTop\\\": 88, \\\"marginW\\\": 88));\\n\\n.tiled-row {\\n\\tdisplay: flex;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".vs-container[data-v-50bb7c53]{overflow-y:scroll;height:100%}.vs-rows-container[data-v-50bb7c53]{box-sizing:border-box;will-change:scroll-position,padding;contain:layout paint style}\", \"\",{\"version\":3,\"sources\":[\"webpack://./src/components/VirtualScrolling.vue\"],\"names\":[],\"mappings\":\"AAEA,+BACC,iBAAA,CACA,WAAA,CAGD,oCACC,qBAAA,CACA,mCAAA,CACA,0BAAA\",\"sourcesContent\":[\"$sizes: (\\\"400\\\": (\\\"count\\\": 3, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"700\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 8), \\\"1024\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1280\\\": (\\\"count\\\": 4, \\\"marginTop\\\": 66, \\\"marginW\\\": 44), \\\"1440\\\": (\\\"count\\\": 5, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"1600\\\": (\\\"count\\\": 6, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2048\\\": (\\\"count\\\": 7, \\\"marginTop\\\": 88, \\\"marginW\\\": 66), \\\"2560\\\": (\\\"count\\\": 8, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"3440\\\": (\\\"count\\\": 9, \\\"marginTop\\\": 88, \\\"marginW\\\": 88), \\\"max\\\": (\\\"count\\\": 10, \\\"marginTop\\\": 88, \\\"marginW\\\": 88));\\n\\n.vs-container {\\n\\toverflow-y: scroll;\\n\\theight: 100%;\\n}\\n\\n.vs-rows-container {\\n\\tbox-sizing: border-box;\\n\\twill-change: scroll-position, padding;\\n\\tcontain: layout paint style;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","\n import API from \"!../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../node_modules/css-loader/dist/cjs.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FavoriteIcon.vue?vue&type=style&index=0&id=a692ce86&prod&lang=scss&scoped=true\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../node_modules/css-loader/dist/cjs.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FavoriteIcon.vue?vue&type=style&index=0&id=a692ce86&prod&lang=scss&scoped=true\";\n export default content && content.locals ? content.locals : undefined;\n","\n import API from \"!../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../node_modules/css-loader/dist/cjs.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./File.vue?vue&type=style&index=0&id=92e450b8&prod&lang=scss&scoped=true\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../node_modules/css-loader/dist/cjs.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./File.vue?vue&type=style&index=0&id=92e450b8&prod&lang=scss&scoped=true\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./FavoriteIcon.vue?vue&type=template&id=a692ce86&scoped=true\"\nimport script from \"./FavoriteIcon.vue?vue&type=script&lang=js\"\nexport * from \"./FavoriteIcon.vue?vue&type=script&lang=js\"\nimport style0 from \"./FavoriteIcon.vue?vue&type=style&index=0&id=a692ce86&prod&lang=scss&scoped=true\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"a692ce86\",\n null\n \n)\n\nexport default component.exports","import { render, staticRenderFns } from \"./File.vue?vue&type=template&id=92e450b8&scoped=true\"\nimport script from \"./File.vue?vue&type=script&lang=js\"\nexport * from \"./File.vue?vue&type=script&lang=js\"\nimport style0 from \"./File.vue?vue&type=style&index=0&id=92e450b8&prod&lang=scss&scoped=true\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"92e450b8\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"files-list-viewer\"},[(_vm.emptyMessage !== '' && _vm.photosCount === 0 && !_vm.loading)?_c('NcEmptyContent',{key:\"emptycontent\",attrs:{\"name\":_vm.emptyMessage}},[_c('PackageVariant',{attrs:{\"slot\":\"icon\"},slot:\"icon\"})],1):_vm._e(),_vm._v(\" \"),_c('TiledLayout',{attrs:{\"base-height\":_vm.baseHeight,\"sections\":_vm.itemsBySections},scopedSlots:_vm._u([{key:\"default\",fn:function({tiledSections}){return _c('VirtualScrolling',{attrs:{\"use-window\":_vm.useWindow,\"container-element\":_vm.containerElement,\"sections\":tiledSections,\"scroll-to-key\":_vm.scrollToSection,\"header-height\":_vm.sectionHeaderHeight},on:{\"need-content\":_vm.needContent},scopedSlots:_vm._u([{key:\"default\",fn:function({visibleSections}){return _vm._l((visibleSections),function(section){return _c('div',{key:section.id},[(section.id !== '')?[(_vm.showPlaceholders)?_c('div',{staticClass:\"files-list-viewer__placeholder\",style:({ 'flex-basis': '100%', height: `${_vm.sectionHeaderHeight}px`})}):_vm._t(\"default\",null,{\"file\":{id: section.id},\"isHeader\":true})]:_vm._e(),_vm._v(\" \"),_c('ul',[_vm._l((section.rows),function(row,rowIndex){return _vm._l((row.items),function(item){return _c('li',{key:item.key,class:{ 'last-tiled-rows': rowIndex === section.rows.length - 1 },style:({ 'flex-basis': `${item.width - 1}px`, height: `${item.height}px`})},[(_vm.showPlaceholders)?_c('div',{staticClass:\"files-list-viewer__placeholder\"}):_vm._t(\"default\",null,{\"file\":item,\"distance\":row.distance})],2)})})],2)],2)})}}])},[_vm._v(\" \"),(_vm.loading && !_vm.showPlaceholders)?_c('NcLoadingIcon',{staticClass:\"files-list-viewer__loader\",attrs:{\"slot\":\"loader\"},slot:\"loader\"}):_vm._e()],1)}}])})],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/**\n * @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>\n *\n * @author Louis Chemineau <louis@chmn.me>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\n/**\n * @typedef {object} TiledItem\n * @property {string} id - Unique id for the item.\n * @property {number} width Real width of the item.\n * @property {number} height Real height of the item.\n * @property {number} ratio The aspect ratio of the item.\n */\n\n/**\n * @typedef {object} Section\n * @property {string} id - Unique id for the section.\n * @property {TiledItem[]} items Real width of the item.\n */\n\n/**\n * @typedef {object} TiledRow\n * @property {TiledItem[]} items - List of item in the row.\n * @property {number} height - Height of the row.\n * @property {string} key - Unique key for the row.\n */\n\n/**\n * @typedef {Section} TiledSection\n * @property {string} key - Unique key for the section.\n * @property {TiledRow[]} rows Real width of the item.\n * @property {number} height - Height of the section.\n */\n\n/**\n * Split items in rows of equal width.\n * The last row will not be forced to match containerWidth.\n *\n * @param {TiledItem[]} items The list of item to split in row of equal width.\n * @param {number} containerWidth The width of a row.\n * @param {number} baseHeight The base height of the rows.\n * @return {TiledRow[]}\n */\nexport function splitItemsInRows(items, containerWidth, baseHeight = 200) {\n\tif (containerWidth === 0) {\n\t\treturn []\n\t}\n\n\tconst rows = []\n\tlet rowNumber = 0\n\tlet currentItem = 0\n\n\twhile (currentItem < items.length) {\n\t\t/** @type { TiledItem[] } */\n\t\tconst rowItems = []\n\n\t\t// Fill the row with new items as long as the width is less than containerWidth.\n\t\tdo {\n\t\t\t// @ts-ignore - We know that items.shift() is not undefined as we always check that items.length > 0.\n\t\t\trowItems.push(items[currentItem++])\n\t\t} while (\n\t\t\tcurrentItem < items.length\n\t\t\t&& computeRowWidth([...rowItems, items[currentItem]], baseHeight) <= containerWidth\n\t\t)\n\n\t\tconst rowHeight = computeRowHeight(\n\t\t\trowItems,\n\t\t\tcontainerWidth,\n\t\t\titems.length === currentItem,\n\t\t\tbaseHeight\n\t\t)\n\n\t\trows[rowNumber] = {\n\t\t\titems: rowItems.map(item => ({ ...item, width: rowHeight * item.ratio, height: rowHeight })),\n\t\t\t// Key to help vue to keep track of the row in VirtualScrolling.\n\t\t\theight: rowHeight,\n\t\t\tkey: rowItems.map(item => item.id).join('-'),\n\t\t}\n\n\t\trowNumber += 1\n\t}\n\n\treturn rows\n}\n\n/**\n *\n * @param {TiledItem[]} items The list of items in the row.\n * @param {number} baseHeight The base height of the rows.\n * @return {number} The width of the row\n */\nfunction computeRowWidth(items, baseHeight) {\n\treturn items\n\t\t.map(item => baseHeight * item.ratio)\n\t\t.reduce((sum, itemWidth) => sum + itemWidth)\n}\n\n/**\n * Compute the row height based on its items and on the container's width.\n *\n * Math time !\n * With Rn the aspect ratio of item n\n * Wn the width of item n\n * Hn the height of item n\n * Wc the width of the container\n * Hr the height of the row\n * For n items we want: Wc = W1 + W2 + ... + Wn\n * We know Rn = Wn / Hn\n * So Wn = Rn * Hn\n * So Wc = (R1 * H1) + (R2 * H2) + ... + (Rn * Hn)\n * But we also want Hr === H1 === H2 === ... === Hn\n * So Wc = (R1 * Hr) + (R2 * Hr) + ... + (Rn * Hr)\n * So Wc = Hr * (R1 + R2 + ... + Rn)\n * So Hr = Wc / (R1 + R2 + ... + Rn)\n *\n * @param {TiledItem[]} items The list of items in the row.\n * @param {number} containerWidth The width of the row.\n * @param {boolean} isLastRow Whether we are computing the height for the last row.\n * @param {number} baseHeight The base height of the rows.\n * @return {number} The height of the row\n */\nfunction computeRowHeight(items, containerWidth, isLastRow, baseHeight) {\n\tconst sumOfItemsRatio = items\n\t\t.map(item => item.ratio)\n\t\t.reduce((sum, itemRatio) => sum + itemRatio\n\t\t)\n\n\tlet rowHeight = containerWidth / sumOfItemsRatio\n\n\t// Exception 1: there is only one item which is larger than containerWidth.\n\t// Limit its height so that itemWidth === containerWidth\n\tif (items.length === 1 && items[0].width > containerWidth) {\n\t\trowHeight = containerWidth / items[0].ratio\n\t}\n\n\t// Exception 2: we reached the last row.\n\t// Force the items width to match containerWidth, and limit their height to baseHeight + 20.\n\tif (isLastRow) {\n\t\trowHeight = Math.min(baseHeight + 20, rowHeight)\n\t}\n\n\treturn rowHeight\n}\n","var render = function render(_c,_vm){return _c('ul',_vm._l((_vm.props.rows),function(row){return _c('div',{key:row.key,staticClass:\"tiled-row\",style:({height: `${row.height}px`})},_vm._l((row.items),function(item){return _c('li',{key:item.id,style:({ width: item.ratio ? `${row.height * item.ratio}px` : '100%', height: `${row.height}px`})},[_vm._t(\"default\",null,{\"row\":row,\"item\":item})],2)}),0)}),0)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/dist/cjs.js!../../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TiledRows.vue?vue&type=style&index=0&id=c1815a46&prod&lang=scss&scoped=true\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/dist/cjs.js!../../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TiledRows.vue?vue&type=style&index=0&id=c1815a46&prod&lang=scss&scoped=true\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./TiledRows.vue?vue&type=template&id=c1815a46&scoped=true&functional=true\"\nvar script = {}\nimport style0 from \"./TiledRows.vue?vue&type=style&index=0&id=c1815a46&prod&lang=scss&scoped=true\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n true,\n null,\n \"c1815a46\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TiledLayout.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/babel-loader/lib/index.js!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TiledLayout.vue?vue&type=script&lang=js\"","<!--\n - @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>\n -\n - @author Louis Chemineau <louis@chmn.me>\n -\n - @license AGPL-3.0-or-later\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n<template>\n\t<div ref=\"tiledLayoutContainer\"\n\t\tclass=\"tiled-container\">\n\t\t<!-- Slot to allow changing the rows before passing them to TiledRows -->\n\t\t<!-- Useful for partially rendering rows like with VirtualScrolling -->\n\t\t<slot :tiled-sections=\"tiledSections\">\n\t\t\t<!-- Default rendering -->\n\t\t\t<TiledRows :rows=\"tiledSections\" />\n\t\t</slot>\n\t</div>\n</template>\n\n<script>\nimport logger from '../../services/logger.js'\nimport { splitItemsInRows } from '../../services/TiledLayout.js'\nimport TiledRows from './TiledRows.vue'\n\nexport default {\n\tname: 'TiledLayout',\n\n\tcomponents: {\n\t\tTiledRows,\n\t},\n\n\tprops: {\n\t\t/** @type {import('vue').PropType<import('../VirtualScrolling.vue').Section[]>} */\n\t\tsections: {\n\t\t\ttype: Array,\n\t\t\trequired: true,\n\t\t},\n\t\tbaseHeight: {\n\t\t\ttype: Number,\n\t\t\tdefault: 200,\n\t\t},\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tcontainerWidth: 0,\n\t\t\t/** @type {ResizeObserver} */\n\t\t\tresizeObserver: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {import('../../services/TiledLayout.js').TiledSection[]} */\n\t\ttiledSections() {\n\t\t\tlogger.debug('[TiledLayout] Computing rows', { items: this.sections })\n\n\t\t\treturn this.sections.map(section => {\n\t\t\t\tconst rows = splitItemsInRows(section.items, this.containerWidth, this.baseHeight)\n\t\t\t\treturn {\n\t\t\t\t\t...section,\n\t\t\t\t\tkey: section.id,\n\t\t\t\t\trows: rows.map(row => ({ ...row, sectionKey: section.id })),\n\t\t\t\t\theight: rows.reduce((totalHeight, row) => totalHeight + row.height, 0),\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.resizeObserver = new ResizeObserver(entries => {\n\t\t\tfor (const entry of entries) {\n\t\t\t\tconst cr = entry.contentRect\n\t\t\t\tif (entry.target.classList.contains('tiled-container')) {\n\t\t\t\t\tthis.containerWidth = cr.width\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tthis.resizeObserver.observe(this.$refs.tiledLayoutContainer)\n\t},\n\n\tbeforeDestroy() {\n\t\tthis.resizeObserver.disconnect()\n\t},\n}\n</script>\n\n<style scoped lang=\"scss\">\n.tiled-container {\n\theight: 100%;\n\n\t.tiled-row {\n\t\tdisplay: flex;\n\t}\n}\n</style>\n","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/dist/cjs.js!../../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TiledLayout.vue?vue&type=style&index=0&id=732189b2&prod&scoped=true&lang=scss\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../node_modules/postcss-loader/dist/cjs.js!../../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./TiledLayout.vue?vue&type=style&index=0&id=732189b2&prod&scoped=true&lang=scss\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./TiledLayout.vue?vue&type=template&id=732189b2&scoped=true\"\nimport script from \"./TiledLayout.vue?vue&type=script&lang=js\"\nexport * from \"./TiledLayout.vue?vue&type=script&lang=js\"\nimport style0 from \"./TiledLayout.vue?vue&type=style&index=0&id=732189b2&prod&scoped=true&lang=scss\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"732189b2\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{ref:\"tiledLayoutContainer\",staticClass:\"tiled-container\"},[_vm._t(\"default\",function(){return [_c('TiledRows',{attrs:{\"rows\":_vm.tiledSections}})]},{\"tiledSections\":_vm.tiledSections})],2)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/**\n * @copyright Copyright (c) 2023 Louis Chemineau <louis@chmn.me>\n *\n * @author Louis Chemineau <louis@chmn.me>\n *\n * @license AGPL-3.0-or-later\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n *\n */\n\nimport { genFileInfo } from '../utils/fileUtils.js'\nimport defaultClient from './DavClient.js'\n\n/**\n * @param {string[]} extraProps - Extra properties to add to the DAV request.\n * @return {string}\n */\nfunction getCollectionFilesDavRequest(extraProps = []) {\n\treturn `<?xml version=\"1.0\"?>\n\t\t\t<d:propfind xmlns:d=\"DAV:\"\n\t\t\t\txmlns:oc=\"http://owncloud.org/ns\"\n\t\t\t\txmlns:nc=\"http://nextcloud.org/ns\"\n\t\t\t\txmlns:ocs=\"http://open-collaboration-services.org/ns\">\n\t\t\t\t<d:prop>\n\t\t\t\t\t<d:getcontentlength />\n\t\t\t\t\t<d:getcontenttype />\n\t\t\t\t\t<d:getetag />\n\t\t\t\t\t<d:getlastmodified />\n\t\t\t\t\t<d:resourcetype />\n\t\t\t\t\t<nc:metadata-photos-size />\n\t\t\t\t\t<nc:metadata-photos-original_date_time />\n\t\t\t\t\t<nc:metadata-files-live-photo />\n\t\t\t\t\t<nc:has-preview />\n\t\t\t\t\t<nc:hidden />\n\t\t\t\t\t<oc:favorite />\n\t\t\t\t\t<oc:fileid />\n\t\t\t\t\t<oc:permissions />\n\t\t\t\t\t${extraProps.join('')}\n\t\t\t\t</d:prop>\n\t\t\t</d:propfind>`\n}\n\n/**\n * @param {string} fileName - The full file's name\n * @param {import('webdav').StatOptions} options - Options to forward to the webdav client.\n * @return {Promise<object>}\n */\nexport async function fetchFile(fileName, options = {}) {\n\ttry {\n\t\tconst response = await defaultClient.stat(fileName, {\n\t\t\tdata: getCollectionFilesDavRequest(),\n\t\t\tdetails: true,\n\t\t\t...options,\n\t\t})\n\n\t\treturn genFileInfo(response.data)\n\t} catch (error) {\n\t\tif (error.code === 'ERR_CANCELED') {\n\t\t\treturn null\n\t\t}\n\n\t\tthrow error\n\t}\n}\n","<!--\n - @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>\n -\n - @author Louis Chemineau <louis@chmn.me>\n -\n - @license AGPL-3.0-or-later\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n<template>\n\t<div v-if=\"!useWindow && containerElement === null\" ref=\"container\" class=\"vs-container\">\n\t\t<div ref=\"rowsContainer\"\n\t\t\tclass=\"vs-rows-container\"\n\t\t\t:style=\"rowsContainerStyle\">\n\t\t\t<slot :visible-sections=\"visibleSections\" />\n\t\t\t<slot name=\"loader\" />\n\t\t</div>\n\t</div>\n\t<div v-else\n\t\tref=\"rowsContainer\"\n\t\tclass=\"vs-rows-container\"\n\t\t:style=\"rowsContainerStyle\">\n\t\t<slot :visible-sections=\"visibleSections\" />\n\t\t<slot name=\"loader\" />\n\t</div>\n</template>\n\n<script>\nimport logger from '../services/logger.js'\n\n/**\n * @typedef {object} Section\n * @property {string} key - Unique key for the section.\n * @property {Row[]} rows - The height of the row.\n * @property {number} height - Height of the section, excluding the header.\n */\n\n/**\n * @typedef {Section} VisibleSection\n * @property {VisibleRow[]} rows - The height of the row.\n */\n\n/**\n * @typedef {object} Row\n * @property {string} key - Unique key for the row.\n * @property {number} height - The height of the row.\n * @property {string} sectionKey - Unique key for the row.\n */\n\n/**\n * @typedef {Row} VisibleRow\n * @property {number} distance - The distance from the visible viewport\n */\n\nexport default {\n\tname: 'VirtualScrolling',\n\n\tprops: {\n\t\t/** @type {import('vue').PropType<Section[]}>} */\n\t\tsections: {\n\t\t\ttype: Array,\n\t\t\trequired: true,\n\t\t},\n\n\t\tcontainerElement: {\n\t\t\ttype: HTMLElement,\n\t\t\tdefault: null,\n\t\t},\n\n\t\tuseWindow: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\theaderHeight: {\n\t\t\ttype: Number,\n\t\t\tdefault: 75,\n\t\t},\n\t\trenderDistance: {\n\t\t\ttype: Number,\n\t\t\tdefault: 0.5,\n\t\t},\n\t\tbottomBufferRatio: {\n\t\t\ttype: Number,\n\t\t\tdefault: 2,\n\t\t},\n\t\tscrollToKey: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tscrollPosition: 0,\n\t\t\tcontainerHeight: 0,\n\t\t\trowsContainerHeight: 0,\n\t\t\t/** @type {ResizeObserver} */\n\t\t\tresizeObserver: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {VisibleSection[]} */\n\t\tvisibleSections() {\n\t\t\tlogger.debug('[VirtualScrolling] Computing visible section', { sections: this.sections })\n\n\t\t\t// Optimisation: get those computed properties once to not go through vue's internal every time we need them.\n\t\t\tconst containerHeight = this.containerHeight\n\t\t\tconst containerTop = this.scrollPosition\n\t\t\tconst containerBottom = containerTop + containerHeight\n\n\t\t\tlet currentRowTop = 0\n\t\t\tlet currentRowBottom = 0\n\n\t\t\t// Compute whether a row should be included in the DOM (shouldRender)\n\t\t\t// And how visible the row is.\n\t\t\tconst visibleSections = this.sections\n\t\t\t\t.map(section => {\n\t\t\t\t\tcurrentRowBottom += this.headerHeight\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...section,\n\t\t\t\t\t\trows: section.rows.reduce((visibleRows, row) => {\n\t\t\t\t\t\t\tcurrentRowTop = currentRowBottom\n\t\t\t\t\t\t\tcurrentRowBottom += row.height\n\n\t\t\t\t\t\t\tlet distance = 0\n\n\t\t\t\t\t\t\tif (currentRowBottom < containerTop) {\n\t\t\t\t\t\t\t\tdistance = (containerTop - currentRowBottom) / containerHeight\n\t\t\t\t\t\t\t} else if (currentRowTop > containerBottom) {\n\t\t\t\t\t\t\t\tdistance = (currentRowTop - containerBottom) / containerHeight\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (distance > this.renderDistance) {\n\t\t\t\t\t\t\t\treturn visibleRows\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t...visibleRows,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t...row,\n\t\t\t\t\t\t\t\t\tdistance,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}, []),\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.filter(section => section.rows.length > 0)\n\n\t\t\t// To allow vue to recycle the DOM elements instead of adding and deleting new ones,\n\t\t\t// we assign a random key to each items. When a item removed, we recycle its key for new items,\n\t\t\t// so vue can replace the content of removed DOM elements with the content of new items, but keep the other DOM elements untouched.\n\t\t\tconst visibleItems = visibleSections\n\t\t\t\t.flatMap(({ rows }) => rows)\n\t\t\t\t.flatMap(({ items }) => items)\n\n\t\t\tvisibleItems.forEach(item => (item.key = this.rowIdToKeyMap[item.id]))\n\n\t\t\tconst usedTokens = visibleItems\n\t\t\t\t.map(({ key }) => key)\n\t\t\t\t.filter(key => key !== undefined)\n\n\t\t\tconst unusedTokens = Object.values(this.rowIdToKeyMap).filter(key => !usedTokens.includes(key))\n\n\t\t\tvisibleItems\n\t\t\t\t.filter(({ key }) => key === undefined)\n\t\t\t\t.forEach(item => (item.key = unusedTokens.pop() ?? Math.random().toString(36).substr(2)))\n\n\t\t\t// this.rowIdToKeyMap is created in the beforeCreate hook, so value changes are not tracked.\n\t\t\t// Therefore, we wont trigger the computation of visibleSections again if we alter the value of this.rowIdToKeyMap.\n\t\t\t// eslint-disable-next-line vue/no-side-effects-in-computed-properties\n\t\t\tthis.rowIdToKeyMap = visibleItems.reduce((finalMapping, { id, key }) => ({ ...finalMapping, [`${id}`]: key }), {})\n\n\t\t\treturn visibleSections\n\t\t},\n\n\t\t/**\n\t\t * Total height of all the rows + some room for the loader.\n\t\t *\n\t\t * @return {number}\n\t\t */\n\t\ttotalHeight() {\n\t\t\tconst loaderHeight = 200\n\n\t\t\treturn this.sections\n\t\t\t\t.map(section => this.headerHeight + section.height)\n\t\t\t\t.reduce((totalHeight, sectionHeight) => totalHeight + sectionHeight, 0) + loaderHeight\n\t\t},\n\n\t\t/**\n\t\t * @return {number}\n\t\t */\n\t\tpaddingTop() {\n\t\t\tif (this.visibleSections.length === 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\n\t\t\tlet paddingTop = 0\n\n\t\t\tfor (const section of this.sections) {\n\t\t\t\tif (section.key !== this.visibleSections[0].rows[0].sectionKey) {\n\t\t\t\t\tpaddingTop += this.headerHeight + section.height\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tfor (const row of section.rows) {\n\t\t\t\t\tif (row.key === this.visibleSections[0].rows[0].key) {\n\t\t\t\t\t\treturn paddingTop\n\t\t\t\t\t}\n\n\t\t\t\t\tpaddingTop += row.height\n\t\t\t\t}\n\n\t\t\t\tpaddingTop += this.headerHeight\n\t\t\t}\n\n\t\t\treturn paddingTop\n\t\t},\n\n\t\t/**\n\t\t * padding-top is used to replace not included item in the container.\n\t\t *\n\t\t * @return {{heigh: string, paddingTop: string}}\n\t\t */\n\t\trowsContainerStyle() {\n\t\t\treturn {\n\t\t\t\theight: `${this.totalHeight}px`,\n\t\t\t\tpaddingTop: `${this.paddingTop}px`,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Whether the user is near the bottom.\n\t\t * If true, then the need-content event will be emitted.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisNearBottom() {\n\t\t\tconst buffer = this.containerHeight * this.bottomBufferRatio\n\t\t\treturn this.scrollPosition + this.containerHeight >= this.totalHeight - buffer\n\t\t},\n\n\t\t/**\n\t\t * @return {HTMLElement}\n\t\t */\n\t\tcontainer() {\n\t\t\tlogger.debug('[VirtualScrolling] Computing container')\n\t\t\tif (this.containerElement !== null) {\n\t\t\t\treturn this.containerElement\n\t\t\t} else if (this.useWindow) {\n\t\t\t\treturn window\n\t\t\t} else {\n\t\t\t\treturn this.$refs.container\n\t\t\t}\n\t\t},\n\t},\n\n\twatch: {\n\t\tisNearBottom(value) {\n\t\t\tlogger.debug('[VirtualScrolling] isNearBottom changed', { value })\n\t\t\tif (value) {\n\t\t\t\tthis.$emit('need-content')\n\t\t\t}\n\t\t},\n\n\t\tvisibleSections() {\n\t\t\t// Re-emit need-content when rows is updated and isNearBottom is still true.\n\t\t\t// If the height of added rows is under `bottomBufferRatio`, `isNearBottom` will still be true so we need more content.\n\t\t\tif (this.isNearBottom) {\n\t\t\t\tthis.$emit('need-content')\n\t\t\t}\n\t\t},\n\n\t\tscrollToKey(key) {\n\t\t\tlet currentRowTopDistanceFromTop = 0\n\n\t\t\tfor (const section of this.sections) {\n\t\t\t\tif (section.key !== key) {\n\t\t\t\t\tcurrentRowTopDistanceFromTop += this.headerHeight + section.height\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tlogger.debug('[VirtualScrolling] Scrolling to', { currentRowTopDistanceFromTop })\n\t\t\tthis.$refs.container.scrollTo({ top: currentRowTopDistanceFromTop, behavior: 'smooth' })\n\t\t},\n\t},\n\n\tbeforeCreate() {\n\t\tthis.rowIdToKeyMap = {}\n\t},\n\n\tmounted() {\n\t\tthis.resizeObserver = new ResizeObserver(entries => {\n\t\t\tfor (const entry of entries) {\n\t\t\t\tconst cr = entry.contentRect\n\t\t\t\tif (entry.target === this.container) {\n\t\t\t\t\tthis.containerHeight = cr.height\n\t\t\t\t}\n\t\t\t\tif (entry.target.classList.contains('vs-rows-container')) {\n\t\t\t\t\tthis.rowsContainerHeight = cr.height\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tif (this.useWindow) {\n\t\t\twindow.addEventListener('resize', this.updateContainerSize, { passive: true })\n\t\t\tthis.containerHeight = window.innerHeight\n\t\t} else {\n\t\t\tthis.resizeObserver.observe(this.container)\n\t\t}\n\n\t\tthis.resizeObserver.observe(this.$refs.rowsContainer)\n\t\tthis.container.addEventListener('scroll', this.updateScrollPosition, { passive: true })\n\t},\n\n\tbeforeDestroy() {\n\t\tif (this.useWindow) {\n\t\t\twindow.removeEventListener('resize', this.updateContainerSize)\n\t\t}\n\n\t\tthis.resizeObserver.disconnect()\n\t\tthis.container.removeEventListener('scroll', this.updateScrollPosition)\n\t},\n\n\tmethods: {\n\t\tupdateScrollPosition() {\n\t\t\tthis._onScrollHandle ??= requestAnimationFrame(() => {\n\t\t\t\tthis._onScrollHandle = null\n\t\t\t\tif (this.useWindow) {\n\t\t\t\t\tthis.scrollPosition = this.container.scrollY\n\t\t\t\t} else {\n\t\t\t\t\tthis.scrollPosition = this.container.scrollTop\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\tupdateContainerSize() {\n\t\t\tthis.containerHeight = window.innerHeight\n\t\t},\n\t},\n}\n</script>\n\n<style scoped lang=\"scss\">\n.vs-container {\n\toverflow-y: scroll;\n\theight: 100%;\n}\n\n.vs-rows-container {\n\tbox-sizing: border-box;\n\twill-change: scroll-position, padding;\n\tcontain: layout paint style;\n}\n</style>\n","import mod from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./VirtualScrolling.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./VirtualScrolling.vue?vue&type=script&lang=js\"","\n import API from \"!../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../node_modules/css-loader/dist/cjs.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./VirtualScrolling.vue?vue&type=style&index=0&id=50bb7c53&prod&scoped=true&lang=scss\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../node_modules/css-loader/dist/cjs.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./VirtualScrolling.vue?vue&type=style&index=0&id=50bb7c53&prod&scoped=true&lang=scss\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./VirtualScrolling.vue?vue&type=template&id=50bb7c53&scoped=true\"\nimport script from \"./VirtualScrolling.vue?vue&type=script&lang=js\"\nexport * from \"./VirtualScrolling.vue?vue&type=script&lang=js\"\nimport style0 from \"./VirtualScrolling.vue?vue&type=style&index=0&id=50bb7c53&prod&scoped=true&lang=scss\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"50bb7c53\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return (!_vm.useWindow && _vm.containerElement === null)?_c('div',{ref:\"container\",staticClass:\"vs-container\"},[_c('div',{ref:\"rowsContainer\",staticClass:\"vs-rows-container\",style:(_vm.rowsContainerStyle)},[_vm._t(\"default\",null,{\"visibleSections\":_vm.visibleSections}),_vm._v(\" \"),_vm._t(\"loader\")],2)]):_c('div',{ref:\"rowsContainer\",staticClass:\"vs-rows-container\",style:(_vm.rowsContainerStyle)},[_vm._t(\"default\",null,{\"visibleSections\":_vm.visibleSections}),_vm._v(\" \"),_vm._t(\"loader\")],2)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","<!--\n - @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>\n -\n - @author Louis Chemineau <louis@chmn.me>\n -\n - @license AGPL-3.0-or-later\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n -\n -->\n<template>\n\t<div class=\"files-list-viewer\">\n\t\t<NcEmptyContent v-if=\"emptyMessage !== '' && photosCount === 0 && !loading\"\n\t\t\tkey=\"emptycontent\"\n\t\t\t:name=\"emptyMessage\">\n\t\t\t<PackageVariant slot=\"icon\" />\n\t\t</NcEmptyContent>\n\n\t\t<TiledLayout :base-height=\"baseHeight\" :sections=\"itemsBySections\">\n\t\t\t<VirtualScrolling slot-scope=\"{tiledSections}\"\n\t\t\t\t:use-window=\"useWindow\"\n\t\t\t\t:container-element=\"containerElement\"\n\t\t\t\t:sections=\"tiledSections\"\n\t\t\t\t:scroll-to-key=\"scrollToSection\"\n\t\t\t\t:header-height=\"sectionHeaderHeight\"\n\t\t\t\t@need-content=\"needContent\">\n\t\t\t\t<template slot-scope=\"{visibleSections}\">\n\t\t\t\t\t<div v-for=\"section of visibleSections\" :key=\"section.id\">\n\t\t\t\t\t\t<template v-if=\"section.id !== ''\">\n\t\t\t\t\t\t\t<!-- Placeholder when initial loading -->\n\t\t\t\t\t\t\t<div v-if=\"showPlaceholders\"\n\t\t\t\t\t\t\t\tclass=\"files-list-viewer__placeholder\"\n\t\t\t\t\t\t\t\t:style=\"{ 'flex-basis': '100%', height: `${sectionHeaderHeight}px`}\" />\n\t\t\t\t\t\t\t<!-- Real file. -->\n\t\t\t\t\t\t\t<slot v-else\n\t\t\t\t\t\t\t\t:file=\"{id: section.id}\"\n\t\t\t\t\t\t\t\t:is-header=\"true\"\n\t\t\t\t\t\t\t\tclass=\"files-list-viewer__section-header\"\n\t\t\t\t\t\t\t\t:style=\"{ 'flex-basis': '100%', height: `${sectionHeaderHeight}px`}\" />\n\t\t\t\t\t\t</template>\n\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t<template v-for=\"(row, rowIndex) of section.rows\">\n\t\t\t\t\t\t\t\t<!--\n\t\t\t\t\t\t\t\t\tWe are subtracting 1 from flex-basis to compensate for rounding issues.\n\t\t\t\t\t\t\t\t\tThe flex algo will then compensate with flex-grow.\n\t\t\t\t\t\t\t\t\t'last-tiled-row' prevents the last row's items from growing.\n\t\t\t\t\t\t\t\t-->\n\t\t\t\t\t\t\t\t<li v-for=\"item of row.items\"\n\t\t\t\t\t\t\t\t\t:key=\"item.key\"\n\t\t\t\t\t\t\t\t\t:class=\"{ 'last-tiled-rows': rowIndex === section.rows.length - 1 }\"\n\t\t\t\t\t\t\t\t\t:style=\"{ 'flex-basis': `${item.width - 1}px`, height: `${item.height}px`}\">\n\t\t\t\t\t\t\t\t\t<!-- Placeholder when initial loading -->\n\t\t\t\t\t\t\t\t\t<div v-if=\"showPlaceholders\" class=\"files-list-viewer__placeholder\" />\n\t\t\t\t\t\t\t\t\t<!-- Real file. -->\n\t\t\t\t\t\t\t\t\t<slot v-else :file=\"item\" :distance=\"row.distance\" />\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</div>\n\t\t\t\t</template>\n\t\t\t\t<NcLoadingIcon v-if=\"loading && !showPlaceholders\" slot=\"loader\" class=\"files-list-viewer__loader\" />\n\t\t\t</VirtualScrolling>\n\t\t</TiledLayout>\n\t</div>\n</template>\n<script>\nimport { mapActions, mapGetters } from 'vuex'\n\nimport PackageVariant from 'vue-material-design-icons/PackageVariant.vue'\n\nimport { NcEmptyContent, NcLoadingIcon } from '@nextcloud/vue'\nimport { subscribe, unsubscribe } from '@nextcloud/event-bus'\n\nimport TiledLayout from '../components/TiledLayout/TiledLayout.vue'\nimport { fetchFile } from '../services/fileFetcher.js'\nimport VirtualScrolling from '../components/VirtualScrolling.vue'\nimport EmptyBox from '../assets/Illustrations/empty.svg'\n\nexport default {\n\tname: 'FilesListViewer',\n\n\tcomponents: {\n\t\tPackageVariant,\n\t\tNcEmptyContent,\n\t\tNcLoadingIcon,\n\t\tTiledLayout,\n\t\tVirtualScrolling,\n\t},\n\n\tprops: {\n\t\t// Array of file ids that should be rendered.\n\t\tfileIds: {\n\t\t\ttype: Array,\n\t\t\tdefault: undefined,\n\t\t},\n\t\t// An object mapping a list of section to a list of fileIds.\n\t\tfileIdsBySection: {\n\t\t\ttype: Object,\n\t\t\tdefault: undefined,\n\t\t},\n\t\t// The list of sorted sections.\n\t\tsections: {\n\t\t\ttype: Array,\n\t\t\tdefault: undefined,\n\t\t},\n\t\t// Whether we should display a loading indicator.\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t\t// Message to display when there is no files.\n\t\temptyMessage: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t\t// The base height to forward to TileLayout.\n\t\tbaseHeight: {\n\t\t\ttype: Number,\n\t\t\tdefault: 200,\n\t\t},\n\t\t// The height to use for section headers.\n\t\tsectionHeaderHeight: {\n\t\t\ttype: Number,\n\t\t\tdefault: 75,\n\t\t},\n\t\t// Instruct VirtualScrolling to scroll to the given section id.\n\t\tscrollToSection: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t\t// The containerElement props to forward to TileLayout.\n\t\tcontainerElement: {\n\t\t\ttype: HTMLElement,\n\t\t\tdefault: null,\n\t\t},\n\t\t// The useWindow props to forward to TileLayout.\n\t\tuseWindow: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tEmptyBox,\n\t\t\tplaceholderFiles: Array(20).fill(0).map((_, index) => {\n\t\t\t\tconst height = 200\n\t\t\t\tconst width = this.croppedLayout ? height : height * (1 + Math.random() * 2)\n\t\t\t\treturn {\n\t\t\t\t\tid: index,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tratio: width / height,\n\t\t\t\t}\n\t\t\t}),\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t...mapGetters([\n\t\t\t'files',\n\t\t]),\n\n\t\t/**\n\t\t * @return {boolean} The list of items to pass to TiledLayout.\n\t\t */\n\t\tshowPlaceholders() {\n\t\t\treturn this.loading && (this.fileIds?.length === 0 || this.sections?.length === 0)\n\t\t},\n\n\t\t/**\n\t\t * @return {{id: string, items: import('../services/TiledLayout.js').TiledItem[][]}[]} The list of items to pass to TiledLayout.\n\t\t */\n\t\titemsBySections() {\n\t\t\tif (this.fileIds !== undefined) {\n\t\t\t\tif (this.showPlaceholders) {\n\t\t\t\t\treturn [{ id: '', items: this.placeholderFiles }]\n\t\t\t\t}\n\n\t\t\t\treturn [{\n\t\t\t\t\tid: '',\n\t\t\t\t\titems: this.fileIds\n\t\t\t\t\t\t.filter(fileId => this.files[fileId])\n\t\t\t\t\t\t.map(this.mapFileToItem),\n\t\t\t\t}]\n\t\t\t}\n\n\t\t\tif (this.sections !== undefined) {\n\t\t\t\tif (this.showPlaceholders) {\n\t\t\t\t\treturn [{ id: 'placeholder', items: this.placeholderFiles }]\n\t\t\t\t}\n\n\t\t\t\treturn this.sections.map((sectionId) => {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: sectionId,\n\t\t\t\t\t\titems: this.fileIdsBySection[sectionId]\n\t\t\t\t\t\t\t.filter(fileId => this.files[fileId])\n\t\t\t\t\t\t\t.map(this.mapFileToItem),\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn []\n\t\t},\n\n\t\tphotosCount() {\n\t\t\treturn this.itemsBySections.map(({ items }) => items.length).reduce((total, length) => total + length, 0)\n\t\t},\n\n\t\t/** @return {boolean} The list of items to pass to TiledLayout. */\n\t\tshowLoader() {\n\t\t\treturn this.loading && (this.fileIds?.length !== 0 || this.sections?.length !== 0)\n\t\t},\n\t\tcroppedLayout() {\n\t\t\treturn this.$store.state.userConfig.croppedLayout\n\t\t},\n\t},\n\n\tmounted() {\n\t\tsubscribe('files:node:updated', this.handleFileUpdated)\n\t},\n\n\tdestroyed() {\n\t\tunsubscribe('files:node:updated', this.handleFileUpdated)\n\t},\n\n\tmethods: {\n\t\t...mapActions([\n\t\t\t'appendFiles',\n\t\t]),\n\n\t\t// Ask the parent for more content.\n\t\tneedContent() {\n\t\t\tthis.$emit('need-content')\n\t\t},\n\n\t\t/**\n\t\t * @param {string} fileId\n\t\t * @return {import('../services/TiledLayout.js').TiledItem[]}\n\t\t */\n\t\tmapFileToItem(fileId) {\n\t\t\tconst file = this.files[fileId]\n\t\t\treturn {\n\t\t\t\tid: file.fileid,\n\t\t\t\twidth: file.metadataPhotosSize.width,\n\t\t\t\theight: file.metadataPhotosSize.height,\n\t\t\t\tratio: this.croppedLayout ? 1 : file.metadataPhotosSize.width / file.metadataPhotosSize.height,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * @param {object} data\n\t\t * @param {string} data.fileid - The file id of the updated file.\n\t\t */\n\t\tasync handleFileUpdated({ fileid }) {\n\t\t\tconst fetchedFile = await fetchFile(this.files[fileid].filename)\n\t\t\tthis.appendFiles([fetchedFile])\n\t\t},\n\t},\n}\n</script>\n<style lang=\"scss\" scoped>\n.files-list-viewer {\n\theight: 100%;\n\tposition: relative;\n\n\t&__placeholder {\n\t\tbackground: var(--color-primary-element-light);\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tborder: 2px solid var(--color-main-background); // Use border so create a separation between images.\n\t}\n\n\t.tiled-container {\n\t\tflex-basis: 0;\n\t}\n\n\tul {\n\t\tdisplay: flex;\n\t\tflex-wrap: wrap;\n\n\t\tli:not(.last-tiled-rows) {\n\t\t\tflex-grow: 1;\n\t\t}\n\t}\n\n\t&__section-header {\n\t\tposition: sticky;\n\t\ttop: 0;\n\t\tz-index: 3;\n\t\tbackground: var(--color-main-background);\n\t}\n\n\t&__loader {\n\t\tmargin: 50px 0;\n\t}\n}\n</style>\n","import mod from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FilesListViewer.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FilesListViewer.vue?vue&type=script&lang=js\"","\n import API from \"!../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../node_modules/css-loader/dist/cjs.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FilesListViewer.vue?vue&type=style&index=0&id=53f8632c&prod&lang=scss&scoped=true\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../node_modules/css-loader/dist/cjs.js!../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../node_modules/postcss-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js??clonedRuleSet-2.use[3]!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FilesListViewer.vue?vue&type=style&index=0&id=53f8632c&prod&lang=scss&scoped=true\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./FilesListViewer.vue?vue&type=template&id=53f8632c&scoped=true\"\nimport script from \"./FilesListViewer.vue?vue&type=script&lang=js\"\nexport * from \"./FilesListViewer.vue?vue&type=script&lang=js\"\nimport style0 from \"./FilesListViewer.vue?vue&type=style&index=0&id=53f8632c&prod&lang=scss&scoped=true\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"53f8632c\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FavoriteIcon.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./FavoriteIcon.vue?vue&type=script&lang=js\"","import mod from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./File.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/babel-loader/lib/index.js!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./File.vue?vue&type=script&lang=js\""],"names":["defineComponent","name","components","NcIconSvgWrapper","data","StarSvg","mounted","$nextTick","_el$setAttribute","el","$el","querySelector","setAttribute","call","methods","t","FavoriteIcon","NcCheckboxRadioSwitch","VideoIcon","PlayCircleIcon","inheritAttrs","props","file","type","Object","required","selected","Boolean","default","allowSelection","distance","Number","initialized","loadedSmall","errorSmall","loadedLarge","errorLarge","computed","ariaLabel","favorite","basename","isImage","mime","startsWith","decodedEtag","etag","replace","srcLarge","getItemURL","srcSmall","isVisible","hasBlurhash","undefined","metadataBlurhash","watch","Promise","all","isCachedPreview","drawBlurhash","beforeDestroy","$refs","imgSmall","src","emitClick","$emit","fileid","onLoadSmall","onLoadLarge","onErrorSmall","onErrorLarge","onToggle","value","id","size","_this$$route","token","$route","params","generateUrl","concat","canvas","width","height","pixels","decode","ctx","getContext","imageData","createImageData","set","putImageData","render","_vm","this","_c","_self","_setupProxy","staticClass","attrs","staticRenderFns","class","source","on","$event","stopPropagation","preventDefault","apply","arguments","includes","metadataFilesLivePhoto","_e","_v","ref","key","imageName","_m","abortController","AbortController","abort","beforeRouteLeave","from","to","next","selection","resetSelection","onFileSelectToggle","_ref","$set","onUncheckFiles","filesIds","forEach","filesId","selectedFileIds","keys","filter","fileId","hotCache","async","previewUrl","_window$caches","cache","window","caches","open","response","match","___CSS_LOADER_EXPORT___","push","module","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","computeRowWidth","items","baseHeight","map","item","ratio","reduce","sum","itemWidth","computeRowHeight","containerWidth","isLastRow","rowHeight","itemRatio","length","Math","min","TiledRows","_l","rows","row","style","_t","sections","Array","resizeObserver","tiledSections","logger","section","rowNumber","currentItem","rowItems","join","splitItemsInRows","sectionKey","totalHeight","ResizeObserver","entries","entry","cr","contentRect","target","classList","contains","observe","tiledLayoutContainer","disconnect","getCollectionFilesDavRequest","containerElement","HTMLElement","useWindow","headerHeight","renderDistance","bottomBufferRatio","scrollToKey","String","scrollPosition","containerHeight","rowsContainerHeight","visibleSections","containerTop","containerBottom","currentRowTop","currentRowBottom","visibleRows","visibleItems","flatMap","_ref2","rowIdToKeyMap","usedTokens","_ref3","unusedTokens","values","_ref4","_unusedTokens$pop","pop","random","toString","substr","finalMapping","_ref5","sectionHeight","paddingTop","rowsContainerStyle","isNearBottom","buffer","container","currentRowTopDistanceFromTop","scrollTo","top","behavior","beforeCreate","addEventListener","updateContainerSize","passive","innerHeight","rowsContainer","updateScrollPosition","removeEventListener","_this$_onScrollHandle","_onScrollHandle","requestAnimationFrame","scrollY","scrollTop","PackageVariant","NcEmptyContent","NcLoadingIcon","TiledLayout","VirtualScrolling","fileIds","fileIdsBySection","loading","emptyMessage","sectionHeaderHeight","scrollToSection","EmptyBox","placeholderFiles","fill","_","index","croppedLayout","mapGetters","showPlaceholders","_this$fileIds","_this$sections","itemsBySections","files","mapFileToItem","sectionId","photosCount","total","showLoader","_this$fileIds2","_this$sections2","$store","state","userConfig","subscribe","handleFileUpdated","destroyed","unsubscribe","mapActions","needContent","metadataPhotosSize","fetchedFile","fileName","defaultClient","details","genFileInfo","error","code","fetchFile","filename","appendFiles","slot","scopedSlots","_u","fn","rowIndex"],"sourceRoot":""}