f7cloud_client/apps/photos/js/TimelineView-oBWAVriN.chunk.mjs.map
root 8b6a0139db f7cloud_client
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 22:59:26 +00:00

1 line
41 KiB
Plaintext

{"version":3,"file":"TimelineView-oBWAVriN.chunk.mjs","sources":["../node_modules/@nextcloud/vue/dist/chunks/NcListItem-B4Uyn2AS.mjs","../src/components/Albums/AlbumPicker.vue","../src/services/downloadFiles.ts","../src/views/TimelineView.vue"],"sourcesContent":["import '../assets/NcListItem-DfaWGP5A.css';\nimport { N as NcActions } from \"./NcActions-B4VZCD8B.mjs\";\nimport { N as NcCounterBubble } from \"./NcCounterBubble-CDfRYl8B.mjs\";\nimport NcVNodes from \"../Components/NcVNodes.mjs\";\nimport { n as normalizeComponent } from \"./_plugin-vue2_normalizer-DU4iP6Vu.mjs\";\nconst _sfc_main = {\n name: \"NcListItem\",\n components: {\n NcActions,\n NcCounterBubble,\n NcVNodes\n },\n props: {\n /**\n * The details text displayed in the upper right part of the component\n */\n details: {\n type: String,\n default: \"\"\n },\n /**\n * Name (first line of text)\n */\n name: {\n type: String,\n default: void 0\n },\n /**\n * Pass in `true` if you want the matching behavior to\n * be non-inclusive: https://router.vuejs.org/api/#exact\n */\n exact: {\n type: Boolean,\n default: false\n },\n /**\n * The route for the router link.\n */\n to: {\n type: [String, Object],\n default: null\n },\n /**\n * The value for the external link\n */\n href: {\n type: String,\n default: \"#\"\n },\n target: {\n type: String,\n default: \"\"\n },\n /**\n * Id for the `<a>` element\n */\n anchorId: {\n type: String,\n default: \"\"\n },\n /**\n * Make subname bold\n */\n bold: {\n type: Boolean,\n default: false\n },\n /**\n * Show the NcListItem in compact design\n */\n compact: {\n type: Boolean,\n default: false\n },\n /**\n * Toggle the active state of the component\n */\n active: {\n type: Boolean,\n default: false\n },\n /**\n * Aria label for the wrapper element\n */\n linkAriaLabel: {\n type: String,\n default: \"\"\n },\n /**\n * Aria label for the actions toggle\n */\n actionsAriaLabel: {\n type: String,\n default: void 0\n },\n /**\n * If different from 0 this component will display the\n * NcCounterBubble component\n */\n counterNumber: {\n type: [Number, String],\n default: 0\n },\n /**\n * Outlined or highlighted state of the counter\n */\n counterType: {\n type: String,\n default: \"\",\n validator(value) {\n return [\"highlighted\", \"outlined\", \"\"].indexOf(value) !== -1;\n }\n },\n /**\n * To be used only when the elements in the actions menu are very important\n */\n forceDisplayActions: {\n type: Boolean,\n default: false\n },\n /**\n * Force the actions to display in a three dot menu\n */\n forceMenu: {\n type: Boolean,\n default: false\n },\n /**\n * Show the list component layout\n */\n oneLine: {\n type: Boolean,\n default: false\n }\n },\n emits: [\n \"click\",\n \"update:menuOpen\"\n ],\n setup() {\n const [major] = window._oc_config?.version.split(\".\", 2) ?? [];\n const isLegacy = major && Number.parseInt(major) < 30;\n return {\n isLegacy\n };\n },\n data() {\n return {\n hovered: false,\n hasActions: false,\n hasSubname: false,\n displayActionsOnHoverFocus: false,\n menuOpen: false,\n hasIndicator: false,\n hasDetails: false\n };\n },\n computed: {\n showAdditionalElements() {\n return !this.displayActionsOnHoverFocus || this.forceDisplayActions;\n },\n showDetails() {\n return (this.details !== \"\" || this.hasDetails) && (!this.displayActionsOnHoverFocus || this.forceDisplayActions);\n }\n },\n watch: {\n menuOpen(newValue) {\n if (!newValue && !this.hovered) {\n this.displayActionsOnHoverFocus = false;\n }\n }\n },\n mounted() {\n this.checkSlots();\n },\n updated() {\n this.checkSlots();\n },\n methods: {\n /**\n * Handle link click\n *\n * @param {MouseEvent|KeyboardEvent} event - Native click or keydown event\n * @param {Function} [navigate] - VueRouter link's navigate if any\n * @param {string} [routerLinkHref] - VueRouter link's href\n */\n onClick(event, navigate, routerLinkHref) {\n this.$emit(\"click\", event);\n if (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {\n return;\n }\n if (routerLinkHref) {\n navigate?.(event);\n event.preventDefault();\n }\n },\n showActions() {\n if (this.hasActions) {\n this.displayActionsOnHoverFocus = true;\n }\n this.hovered = false;\n },\n hideActions() {\n this.displayActionsOnHoverFocus = false;\n },\n /**\n * @param {FocusEvent} event UI event\n */\n handleBlur(event) {\n if (this.menuOpen) {\n return;\n }\n if (this.$refs[\"list-item\"].contains(event.relatedTarget)) {\n return;\n }\n this.hideActions();\n },\n /**\n * Hide the actions on mouseleave unless the menu is open\n */\n handleMouseleave() {\n if (!this.menuOpen) {\n this.displayActionsOnHoverFocus = false;\n }\n this.hovered = false;\n },\n handleMouseover() {\n this.showActions();\n this.hovered = true;\n },\n handleActionsUpdateOpen(e) {\n this.menuOpen = e;\n this.$emit(\"update:menuOpen\", e);\n },\n // Check if subname and actions slots are populated\n checkSlots() {\n if (this.hasActions !== !!this.$slots.actions) {\n this.hasActions = !!this.$slots.actions;\n }\n if (this.hasSubname !== !!this.$slots.subname) {\n this.hasSubname = !!this.$slots.subname;\n }\n if (this.hasIndicator !== !!this.$slots.indicator) {\n this.hasIndicator = !!this.$slots.indicator;\n }\n if (this.hasDetails !== !!this.$slots.details) {\n this.hasDetails = !!this.$slots.details;\n }\n }\n }\n};\nvar _sfc_render = function render() {\n var _vm = this, _c = _vm._self._c;\n return _c(_vm.to ? \"router-link\" : \"NcVNodes\", { tag: \"component\", attrs: { \"custom\": _vm.to ? true : null, \"to\": _vm.to, \"exact\": _vm.to ? _vm.exact : null }, scopedSlots: _vm._u([{ key: \"default\", fn: function({ href: routerLinkHref, navigate, isActive }) {\n return [_c(\"li\", { staticClass: \"list-item__wrapper\", class: { \"list-item__wrapper--active\": isActive || _vm.active } }, [_c(\"div\", { ref: \"list-item\", staticClass: \"list-item\", class: {\n \"list-item--compact\": _vm.compact,\n \"list-item--legacy\": _vm.isLegacy,\n \"list-item--one-line\": _vm.oneLine\n }, on: { \"mouseover\": _vm.handleMouseover, \"mouseleave\": _vm.handleMouseleave } }, [_c(\"a\", { staticClass: \"list-item__anchor\", attrs: { \"id\": _vm.anchorId || void 0, \"aria-label\": _vm.linkAriaLabel, \"href\": routerLinkHref || _vm.href, \"target\": _vm.target || (_vm.href === \"#\" ? void 0 : \"_blank\"), \"rel\": _vm.href === \"#\" ? void 0 : \"noopener noreferrer\" }, on: { \"focus\": _vm.showActions, \"focusout\": _vm.handleBlur, \"click\": function($event) {\n return _vm.onClick($event, navigate, routerLinkHref);\n }, \"keydown\": function($event) {\n if (!$event.type.indexOf(\"key\") && _vm._k($event.keyCode, \"esc\", 27, $event.key, [\"Esc\", \"Escape\"])) return null;\n return _vm.hideActions.apply(null, arguments);\n } } }, [_vm._t(\"icon\"), _c(\"div\", { staticClass: \"list-item-content\" }, [_c(\"div\", { staticClass: \"list-item-content__main\" }, [_c(\"div\", { staticClass: \"list-item-content__name\" }, [_vm._t(\"name\", function() {\n return [_vm._v(_vm._s(_vm.name))];\n })], 2), _vm.hasSubname ? _c(\"div\", { staticClass: \"list-item-content__subname\", class: { \"list-item-content__subname--bold\": _vm.bold } }, [_vm._t(\"subname\")], 2) : _vm._e()]), _c(\"div\", { staticClass: \"list-item-content__details\" }, [_vm.showDetails ? _c(\"div\", { staticClass: \"list-item-details__details\" }, [_vm._t(\"details\", function() {\n return [_vm._v(_vm._s(_vm.details))];\n })], 2) : _vm._e(), _vm.counterNumber || _vm.hasIndicator ? _c(\"div\", { directives: [{ name: \"show\", rawName: \"v-show\", value: _vm.showAdditionalElements, expression: \"showAdditionalElements\" }], staticClass: \"list-item-details__extra\" }, [_vm.counterNumber ? _c(\"NcCounterBubble\", { staticClass: \"list-item-details__counter\", attrs: { \"active\": isActive || _vm.active, \"type\": _vm.counterType } }, [_vm._v(\" \" + _vm._s(_vm.counterNumber) + \" \")]) : _vm._e(), _vm.hasIndicator ? _c(\"span\", { staticClass: \"list-item-details__indicator\" }, [_vm._t(\"indicator\")], 2) : _vm._e()], 1) : _vm._e()])])], 2), _vm.$slots[\"extra-actions\"] ? _c(\"div\", { staticClass: \"list-item-content__extra-actions\" }, [_vm._t(\"extra-actions\")], 2) : _vm._e(), _c(\"div\", { directives: [{ name: \"show\", rawName: \"v-show\", value: _vm.forceDisplayActions || _vm.displayActionsOnHoverFocus, expression: \"forceDisplayActions || displayActionsOnHoverFocus\" }], staticClass: \"list-item-content__actions\", on: { \"focusout\": _vm.handleBlur } }, [_c(\"NcActions\", { ref: \"actions\", attrs: { \"primary\": isActive || _vm.active, \"force-menu\": _vm.forceMenu, \"aria-label\": _vm.actionsAriaLabel }, on: { \"update:open\": _vm.handleActionsUpdateOpen }, scopedSlots: _vm._u([_vm.$slots[\"actions-icon\"] ? { key: \"icon\", fn: function() {\n return [_vm._t(\"actions-icon\")];\n }, proxy: true } : null], null, true) }, [_vm._t(\"actions\")], 2)], 1), _vm.$slots.extra ? _c(\"div\", { staticClass: \"list-item__extra\" }, [_vm._t(\"extra\")], 2) : _vm._e()])])];\n } }], null, true) });\n};\nvar _sfc_staticRenderFns = [];\nvar __component__ = /* @__PURE__ */ normalizeComponent(\n _sfc_main,\n _sfc_render,\n _sfc_staticRenderFns,\n false,\n null,\n \"40599719\"\n);\nconst NcListItem = __component__.exports;\nexport {\n NcListItem as N\n};\n//# sourceMappingURL=NcListItem-B4Uyn2AS.mjs.map\n","<!--\n - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n<template>\n\t<div v-if=\"!showAlbumCreationForm\" class=\"album-picker\">\n\t\t<h2>\n\t\t\t{{ t('photos', 'Add to Album') }}\n\t\t\t<NcLoadingIcon v-if=\"loadingCollections\" class=\"loading-icon\" />\n\t\t</h2>\n\n\t\t<ul class=\"albums-container\">\n\t\t\t<NcListItem\n\t\t\t\tv-for=\"album in allAlbums\"\n\t\t\t\t:key=\"album.attributes.filename\"\n\t\t\t\tclass=\"album\"\n\t\t\t\t:name=\"originalName(album)\"\n\t\t\t\t:aria-label=\"t('photos', 'Add selection to album {albumName}', { albumName: album.basename })\"\n\t\t\t\t@click=\"pickAlbum(album)\">\n\t\t\t\t<template slot=\"icon\">\n\t\t\t\t\t<img v-if=\"album.attributes['last-photo'] !== -1\" class=\"album__image\" :src=\"album.attributes['last-photo'] | toCoverUrl\">\n\t\t\t\t\t<div v-else class=\"album__image album__image--placeholder\">\n\t\t\t\t\t\t<ImageMultipleOutline :size=\"32\" />\n\t\t\t\t\t</div>\n\t\t\t\t</template>\n\n\t\t\t\t<template #subname>\n\t\t\t\t\t{{ n('photos', '%n item', '%n photos and videos', album.attributes.nbItems) }}\n\t\t\t\t\t<template v-if=\"isSharedAlbum(album)\">\n\t\t\t\t\t\t⸱ {{ t('photos', 'Shared by') }}&nbsp;<NcUserBubble :display-name=\"album.attributes.collaborators[0].label\" :user=\"album.attributes.collaborators[0].id\" />\n\t\t\t\t\t</template>\n\t\t\t\t</template>\n\t\t\t</NcListItem>\n\t\t</ul>\n\n\t\t<NcButton\n\t\t\t:aria-label=\"t('photos', 'Create a new album.')\"\n\t\t\tclass=\"new-album-button\"\n\t\t\ttype=\"tertiary\"\n\t\t\t@click=\"showAlbumCreationForm = true\">\n\t\t\t<template #icon>\n\t\t\t\t<Plus />\n\t\t\t</template>\n\t\t\t{{ t('photos', 'Create new album') }}\n\t\t</NcButton>\n\t</div>\n\n\t<AlbumForm\n\t\tv-else\n\t\t:display-back-button=\"true\"\n\t\t:title=\"t('photos', 'New album')\"\n\t\t@back=\"showAlbumCreationForm = false\"\n\t\t@done=\"albumCreatedHandler\" />\n</template>\n\n<script lang='ts'>\nimport type { Album } from '../../store/albums.ts'\n\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { translate, translatePlural } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { defineComponent } from 'vue'\nimport NcButton from '@nextcloud/vue/components/NcButton'\nimport NcListItem from '@nextcloud/vue/components/NcListItem'\nimport NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'\nimport NcUserBubble from '@nextcloud/vue/components/NcUserBubble'\nimport ImageMultipleOutline from 'vue-material-design-icons/ImageMultipleOutline.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport AlbumForm from './AlbumForm.vue'\nimport FetchCollectionsMixin from '../../mixins/FetchCollectionsMixin.ts'\nimport { albumsExtraProps } from '../../store/albums.ts'\n\nexport default defineComponent({\n\tname: 'AlbumPicker',\n\n\tcomponents: {\n\t\tPlus,\n\t\tImageMultipleOutline,\n\t\tNcButton,\n\t\tNcListItem,\n\t\tNcLoadingIcon,\n\t\tNcUserBubble,\n\t\tAlbumForm,\n\t},\n\n\tfilters: {\n\t\ttoCoverUrl(fileId: string): string {\n\t\t\treturn generateUrl(`/apps/photos/api/v1/preview/${fileId}?x=${64}&y=${64}`)\n\t\t},\n\t},\n\n\tmixins: [FetchCollectionsMixin],\n\n\tdata() {\n\t\treturn {\n\t\t\tshowAlbumCreationForm: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\talbums() {\n\t\t\treturn this.$store.getters.albums\n\t\t},\n\n\t\tsharedAlbums() {\n\t\t\treturn this.$store.getters.sharedAlbums\n\t\t},\n\n\t\tallAlbums() {\n\t\t\treturn [...Object.values(this.albums), ...Object.values(this.sharedAlbums)] as Album[]\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.fetchAlbumList()\n\t},\n\n\tmethods: {\n\t\tasync fetchAlbumList() {\n\t\t\tawait this.fetchCollections(`/photos/${getCurrentUser()?.uid}/albums`, albumsExtraProps)\n\t\t\tawait this.fetchCollections(`/photos/${getCurrentUser()?.uid}/sharedalbums`, albumsExtraProps)\n\t\t},\n\n\t\talbumCreatedHandler() {\n\t\t\tthis.showAlbumCreationForm = false\n\t\t\tthis.fetchAlbumList()\n\t\t},\n\n\t\tpickAlbum(album: Album) {\n\t\t\tthis.$emit('album-picked', album)\n\t\t},\n\n\t\tisSharedAlbum(album: Album) {\n\t\t\treturn album.path.match(/^\\/photos\\/.+\\/sharedalbums\\//) !== null\n\t\t},\n\n\t\toriginalName(album: Album) {\n\t\t\tif (this.isSharedAlbum(album)) {\n\t\t\t\treturn album.basename.replace(new RegExp(`\\\\(${album.attributes.collaborators[0].id}\\\\)$`), '')\n\t\t\t} else {\n\t\t\t\treturn album.basename\n\t\t\t}\n\t\t},\n\n\t\tt: translate,\n\t\tn: translatePlural,\n\t},\n})\n</script>\n\n<style lang=\"scss\" scoped>\n.album-picker {\n\tpadding: 32px;\n\tpadding-top: 16px;\n\n\th2 {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\theight: 60px;\n\n\t\t.loading-icon {\n\t\t\tmargin-inline-start: 32px;\n\t\t}\n\t}\n\n\t.albums-container {\n\t\tmin-height: 150px;\n\t\tmax-height: 350px;\n\t\toverflow-x: scroll;\n\t\tpadding: 2px;\n\n\t\t.album {\n\n\t\t\t:deep(.list-item) {\n\t\t\t\tpadding: 8px 16px;\n\t\t\t\tbox-sizing: border-box;\n\t\t\t}\n\n\t\t\t&:not(:last-child) {\n\t\t\t\tmargin-bottom: 16px;\n\t\t\t}\n\n\t\t\t&__image {\n\t\t\t\twidth: 40px;\n\t\t\t\theight: 40px;\n\t\t\t\tobject-fit: none;\n\t\t\t\tborder-radius: var(--border-radius);\n\n\t\t\t\t&--placeholder {\n\t\t\t\t\tbackground: var(--color-primary-element-light);\n\n\t\t\t\t\t:deep(.material-design-icon) {\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\n\t\t\t\t\t\t.material-design-icon__svg {\n\t\t\t\t\t\t\tfill: var(--color-primary-element);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t.new-album-button {\n\t\tmargin-top: 32px;\n\t}\n}\n</style>\n","/**\n * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport axios from '@nextcloud/axios'\nimport {\n\ttype Node,\n\n\tFileType,\n} from '@nextcloud/files'\n\n/**\n * Trigger downloading a file.\n *\n * @param url The url of the asset to download\n * @param name Optionally the recommended name of the download (browsers might ignore it)\n */\nasync function triggerDownload(url: string, name?: string) {\n\t// try to see if the resource is still available\n\tawait axios.head(url)\n\n\tconst hiddenElement = document.createElement('a')\n\thiddenElement.download = name ?? ''\n\thiddenElement.href = url\n\thiddenElement.click()\n}\n\n/**\n * Find the longest common path prefix of both input paths\n *\n * @param first The first path\n * @param second The second path\n */\nfunction longestCommonPath(first: string, second: string): string {\n\tconst firstSegments = first.split('/').filter(Boolean)\n\tconst secondSegments = second.split('/').filter(Boolean)\n\tlet base = ''\n\tfor (const [index, segment] of firstSegments.entries()) {\n\t\tif (index >= second.length) {\n\t\t\tbreak\n\t\t}\n\t\tif (segment !== secondSegments[index]) {\n\t\t\tbreak\n\t\t}\n\t\tconst sep = base === '' ? '' : '/'\n\t\tbase = `${base}${sep}${segment}`\n\t}\n\treturn base\n}\n\n/**\n * Download the given nodes.\n *\n * If only one node is given, it will be downloaded directly.\n * If multiple nodes are given, they will be zipped and downloaded.\n *\n * @param nodes The node(s) to download\n */\nexport async function downloadFiles(nodes: Node[]) {\n\tlet url: URL\n\n\tif (nodes.length === 1) {\n\t\tif (nodes[0]!.type === FileType.File) {\n\t\t\tawait triggerDownload(nodes[0]!.encodedSource, nodes[0]!.displayname)\n\t\t\treturn\n\t\t} else {\n\t\t\turl = new URL(nodes[0]!.encodedSource)\n\t\t\turl.searchParams.append('accept', 'zip')\n\t\t}\n\t} else {\n\t\turl = new URL(nodes[0]!.encodedSource)\n\t\tlet base = url.pathname\n\t\tfor (const node of nodes.slice(1)) {\n\t\t\tbase = longestCommonPath(base, (new URL(node.encodedSource).pathname))\n\t\t}\n\t\turl.pathname = base\n\n\t\t// The URL contains the path encoded so we need to decode as the query.append will re-encode it\n\t\tconst filenames = nodes.map((node) => decodeURIComponent(node.encodedSource.slice(url.href.length + 1)))\n\t\turl.searchParams.append('accept', 'zip')\n\t\turl.searchParams.append('files', JSON.stringify(filenames))\n\t}\n\n\tif (url.pathname.at(-1) !== '/') {\n\t\turl.pathname = `${url.pathname}/`\n\t}\n\n\tawait triggerDownload(url.href)\n}\n","<!--\n - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<template>\n\t<!-- Errors handlers -->\n\t<div v-if=\"errorFetchingFiles\" class=\"timeline__empty-content\">\n\t\t<NcEmptyContent\n\t\t\tv-if=\"errorFetchingFiles === 404\"\n\t\t\t:name=\"t('photos', 'One of the source folders does not exist')\">\n\t\t\t<FolderAlertOutline slot=\"icon\" />\n\t\t\t<PhotosSourceLocationsSettings\n\t\t\t\tslot=\"action\"\n\t\t\t\tclass=\"timeline__update_source_directory\" />\n\t\t</NcEmptyContent>\n\t\t<NcEmptyContent v-else :name=\"t('photos', 'An error occurred')\">\n\t\t\t<AlertCircleOutline slot=\"icon\" />\n\t\t</NcEmptyContent>\n\t</div>\n\n\t<div v-else class=\"timeline\">\n\t\t<!-- Header -->\n\t\t<HeaderNavigation\n\t\t\tkey=\"navigation\"\n\t\t\t:loading=\"loadingCount > 0\"\n\t\t\t:path=\"'/'\"\n\t\t\t:title=\"rootTitle\"\n\t\t\t:root-title=\"rootTitle\"\n\t\t\t@refresh=\"resetFetchFilesState\">\n\t\t\t<div class=\"timeline__header__left\">\n\t\t\t\t<!-- TODO: UploadPicker -->\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"selectedFileIds.length === 0\"\n\t\t\t\t\tref=\"newAlbumButton\"\n\t\t\t\t\t:aria-label=\"createAlbumButtonLabel\"\n\t\t\t\t\tdata-cy-header-action=\"create-album\"\n\t\t\t\t\t@click=\"showAlbumCreationForm = true\">\n\t\t\t\t\t{{ createAlbumButtonLabel }}\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<PlusBoxMultipleOutline />\n\t\t\t\t\t</template>\n\t\t\t\t</NcButton>\n\n\t\t\t\t<template v-else>\n\t\t\t\t\t<NcButton\n\t\t\t\t\t\t:close-after-click=\"true\"\n\t\t\t\t\t\ttype=\"primary\"\n\t\t\t\t\t\t:aria-label=\"t('photos', 'Add to album')\"\n\t\t\t\t\t\tdata-cy-header-action=\"add-to-album\"\n\t\t\t\t\t\t@click=\"showAlbumPicker = true\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<Plus />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t<template v-if=\"!isMobile\" #default>\n\t\t\t\t\t\t\t{{ t('photos', 'Add to album') }}\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcButton>\n\n\t\t\t\t\t<NcButton\n\t\t\t\t\t\tv-if=\"selectedFileIds.length > 0\"\n\t\t\t\t\t\t:aria-label=\"t('photos', 'Unselect all')\"\n\t\t\t\t\t\tdata-cy-header-action=\"unselect-all\"\n\t\t\t\t\t\t@click=\"resetSelection\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<Close />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t<template v-if=\"!isMobile\" #default>\n\t\t\t\t\t\t\t{{ t('photos', 'Unselect all') }}\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcButton>\n\n\t\t\t\t\t<NcActions :aria-label=\"t('photos', 'Open actions menu')\">\n\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\tdata-cy-header-action=\"download-selection\"\n\t\t\t\t\t\t\t:close-after-click=\"true\"\n\t\t\t\t\t\t\t:aria-label=\"t('photos', 'Download selected files')\"\n\t\t\t\t\t\t\t@click=\"downloadSelectedFiles\">\n\t\t\t\t\t\t\t{{ t('photos', 'Download selected files') }}\n\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<DownloadOutline />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcActionButton>\n\n\t\t\t\t\t\t<ActionFavorite :selected-file-ids=\"selectedFileIds\" />\n\n\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\t:close-after-click=\"true\"\n\t\t\t\t\t\t\t:aria-label=\"t('photos', 'Delete selection')\"\n\t\t\t\t\t\t\tdata-cy-header-action=\"delete-selection\"\n\t\t\t\t\t\t\t@click=\"deleteSelection\">\n\t\t\t\t\t\t\t{{ t('photos', 'Delete selection') }}\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<DeleteOutline />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t</NcActions>\n\t\t\t\t</template>\n\t\t\t</div>\n\t\t</HeaderNavigation>\n\n\t\t<FilesListViewer\n\t\t\tref=\"filesListViewer\"\n\t\t\t:container-element=\"appContent\"\n\t\t\tclass=\"timeline__file-list\"\n\t\t\t:file-ids-by-section=\"fileIdsByMonth\"\n\t\t\t:sections=\"monthsList\"\n\t\t\t:loading=\"loadingFiles\"\n\t\t\t:base-height=\"isMobile ? 120 : 200\"\n\t\t\t:empty-message=\"t('photos', 'No photos or videos in here')\"\n\t\t\t@need-content=\"getContent\">\n\t\t\t<template slot-scope=\"{ file, isHeader, distance }\">\n\t\t\t\t<h2\n\t\t\t\t\tv-if=\"isHeader\"\n\t\t\t\t\t:id=\"`file-picker-section-header-${file.id}`\"\n\t\t\t\t\tclass=\"section-header\">\n\t\t\t\t\t<b>{{ file.id | dateMonth }}</b>\n\t\t\t\t\t{{ file.id | dateYear }}\n\t\t\t\t</h2>\n\t\t\t\t<FileComponent\n\t\t\t\t\tv-else\n\t\t\t\t\t:file=\"files[file.id]\"\n\t\t\t\t\t:allow-selection=\"true\"\n\t\t\t\t\t:selected=\"selection[file.id] === true\"\n\t\t\t\t\t:distance=\"distance\"\n\t\t\t\t\t@click=\"openViewer\"\n\t\t\t\t\t@select-toggled=\"onFileSelectToggle\" />\n\t\t\t</template>\n\t\t</FilesListViewer>\n\n\t\t<NcModal\n\t\t\tv-if=\"showAlbumCreationForm\"\n\t\t\tkey=\"albumCreationForm\"\n\t\t\tlabel-id=\"new-album-form\"\n\t\t\t:set-return-focus=\"$refs.newAlbumButton?.$el\"\n\t\t\t@close=\"showAlbumCreationForm = false\">\n\t\t\t<h2 class=\"timeline__heading\">\n\t\t\t\t{{ t('photos', 'New album') }}\n\t\t\t</h2>\n\t\t\t<AlbumForm :filters-value=\"selectedFilters\" @done=\"handleFormCreationDone\" />\n\t\t</NcModal>\n\n\t\t<NcModal\n\t\t\tv-if=\"showAlbumPicker\"\n\t\t\tkey=\"albumPicker\"\n\t\t\tlabel-id=\"album-picker\"\n\t\t\t@close=\"showAlbumPicker = false\">\n\t\t\t<AlbumPicker @album-picked=\"addSelectionToAlbum\" />\n\t\t</NcModal>\n\t</div>\n</template>\n\n<script lang='ts'>\nimport type { PropType } from 'vue'\nimport type { Album } from '../store/albums.ts'\n\nimport { subscribe, unsubscribe } from '@nextcloud/event-bus'\nimport { t } from '@nextcloud/l10n'\nimport moment from '@nextcloud/moment'\nimport { useIsMobile } from '@nextcloud/vue/composables/useIsMobile'\nimport { storeToRefs } from 'pinia'\nimport NcActionButton from '@nextcloud/vue/components/NcActionButton'\nimport NcActions from '@nextcloud/vue/components/NcActions'\nimport NcButton from '@nextcloud/vue/components/NcButton'\nimport NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'\nimport NcModal from '@nextcloud/vue/components/NcModal'\nimport AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport FolderAlertOutline from 'vue-material-design-icons/FolderAlertOutline.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport PlusBoxMultipleOutline from 'vue-material-design-icons/PlusBoxMultipleOutline.vue'\nimport DeleteOutline from 'vue-material-design-icons/TrashCanOutline.vue'\nimport DownloadOutline from 'vue-material-design-icons/TrayArrowDown.vue'\nimport ActionFavorite from '../components/Actions/ActionFavorite.vue'\nimport AlbumForm from '../components/Albums/AlbumForm.vue'\nimport AlbumPicker from '../components/Albums/AlbumPicker.vue'\nimport FileComponent from '../components/FileComponent.vue'\nimport FilesListViewer from '../components/FilesListViewer.vue'\nimport HeaderNavigation from '../components/HeaderNavigation.vue'\nimport PhotosSourceLocationsSettings from '../components/Settings/PhotosSourceLocationsSettings.vue'\nimport FetchFilesMixin from '../mixins/FetchFilesMixin.ts'\nimport FilesByMonthMixin from '../mixins/FilesByMonthMixin.ts'\nimport FilesSelectionMixin from '../mixins/FilesSelectionMixin.ts'\nimport { allMimes } from '../services/AllowedMimes.ts'\nimport { downloadFiles } from '../services/downloadFiles.ts'\nimport useFilterStore from '../store/filters.ts'\nimport { configChangedEvent } from '../store/userConfig.ts'\nimport { toViewerFileInfo } from '../utils/fileUtils.ts'\n\nexport default {\n\tname: 'TimelineView',\n\tcomponents: {\n\t\tDeleteOutline,\n\t\tPlusBoxMultipleOutline,\n\t\tDownloadOutline,\n\t\tClose,\n\t\tPlus,\n\t\tFolderAlertOutline,\n\t\tNcEmptyContent,\n\t\tNcModal,\n\t\tNcActions,\n\t\tNcActionButton,\n\t\tNcButton,\n\t\tAlbumForm,\n\t\tAlbumPicker,\n\t\tFilesListViewer,\n\t\tFileComponent,\n\t\tActionFavorite,\n\t\tHeaderNavigation,\n\t\tPhotosSourceLocationsSettings,\n\t\tAlertCircleOutline,\n\t},\n\n\tfilters: {\n\t\tdateMonth(date: string): string {\n\t\t\treturn moment(date, 'YYYYMM').format('MMMM')\n\t\t},\n\n\t\tdateYear(date: string): string {\n\t\t\treturn moment(date, 'YYYYMM').format('YYYY')\n\t\t},\n\t},\n\n\tmixins: [\n\t\tFetchFilesMixin,\n\t\tFilesSelectionMixin,\n\t\tFilesByMonthMixin,\n\t],\n\n\tbeforeRouteLeave(to, from, next) {\n\t\tthis.appContent?.scrollTo(0, 0)\n\t\tnext()\n\t\tObject.keys(this.selectedFilters).forEach((key) => {\n\t\t\tthis.selectedFilters[key] = []\n\t\t})\n\t},\n\n\tprops: {\n\t\tonlyFavorites: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\tmimesType: {\n\t\t\ttype: Array as PropType<string[]>,\n\t\t\tdefault: () => allMimes,\n\t\t},\n\n\t\tonThisDay: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\trootTitle: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\t},\n\n\tsetup() {\n\t\tconst isMobile = useIsMobile()\n\n\t\tconst filtersStore = useFilterStore()\n\t\tconst { selectedFilters, filtersQuery } = storeToRefs(filtersStore)\n\n\t\treturn {\n\t\t\tisMobile,\n\t\t\tselectedFilters,\n\t\t\tfiltersQuery,\n\t\t}\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tloadingCount: 0,\n\t\t\tshowAlbumCreationForm: false,\n\t\t\tshowAlbumPicker: false,\n\t\t\tappContent: document.getElementById('app-content-vue'),\n\t\t\tshowFilters: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tfiles() {\n\t\t\treturn this.$store.state.files.files\n\t\t},\n\n\t\tcreateAlbumButtonLabel() {\n\t\t\tif (Object.keys(this.selectedFilters).length > 0) {\n\t\t\t\treturn this.t('photos', 'Create new album from filters')\n\t\t\t} else {\n\t\t\t\treturn this.t('photos', 'Create new album')\n\t\t\t}\n\t\t},\n\t},\n\n\twatch: {\n\t\tfiltersQuery() {\n\t\t\tthis.resetFetchFilesState()\n\t\t\tthis.getContent()\n\t\t},\n\t},\n\n\tmounted() {\n\t\tsubscribe(configChangedEvent, this.handleUserConfigChange)\n\t},\n\n\tdestroyed() {\n\t\tunsubscribe(configChangedEvent, this.handleUserConfigChange)\n\t},\n\n\tmethods: {\n\t\tgetContent() {\n\t\t\tthis.fetchFiles({\n\t\t\t\tmimesType: this.mimesType,\n\t\t\t\tonThisDay: this.onThisDay,\n\t\t\t\tonlyFavorites: this.onlyFavorites,\n\t\t\t\textraFilters: this.filtersQuery,\n\t\t\t})\n\t\t},\n\n\t\topenViewer(fileId: string) {\n\t\t\twindow.OCA.Viewer.open({\n\t\t\t\tfileInfo: toViewerFileInfo(this.files[fileId]),\n\t\t\t\tlist: Object.values(this.fileIdsByMonth).flat().map((fileId) => toViewerFileInfo(this.files[fileId])),\n\t\t\t})\n\t\t},\n\n\t\topenUploader() {\n\t\t\t// TODO: finish when implementing upload\n\t\t},\n\n\t\tasync addSelectionToAlbum(album: Album) {\n\t\t\tthis.showAlbumPicker = false\n\t\t\tawait this.$store.dispatch('addFilesToCollection', { collectionFileName: album.root + album.path, fileIdsToAdd: this.selectedFileIds })\n\t\t},\n\n\t\tasync deleteSelection() {\n\t\t\t// Need to store the file ids so it is not changed before the deleteFiles call.\n\t\t\tconst fileIds = this.selectedFileIds\n\t\t\tthis.onUncheckFiles(fileIds)\n\t\t\tthis.fetchedFileIds = this.fetchedFileIds.filter((fileid) => !fileIds.includes(fileid))\n\t\t\tawait this.$store.dispatch('deleteFiles', fileIds)\n\t\t},\n\n\t\thandleUserConfigChange({ key }) {\n\t\t\tif (key === 'photosSourceFolders') {\n\t\t\t\tthis.resetFetchFilesState()\n\t\t\t}\n\t\t},\n\n\t\thandleFormCreationDone({ album }: { album: Album }) {\n\t\t\tthis.showAlbumCreationForm = false\n\t\t\tthis.$router.push(`/albums/${album.basename}`)\n\t\t},\n\n\t\tdownloadSelectedFiles() {\n\t\t\tconst fileIds = this.selectedFileIds\n\t\t\tthis.onUncheckFiles(fileIds)\n\t\t\tdownloadFiles(fileIds.map((fileId) => this.files[fileId]))\n\t\t},\n\n\t\tt,\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.timeline {\n\tdisplay: flex;\n\tflex-direction: column;\n\n\t&__empty-content {\n\t\theight: 100%;\n\n\t\t.empty-content {\n\t\t\theight: 100%;\n\t\t}\n\n\t\t.timeline__update_source_directory {\n\t\t\talign-items: center;\n\n\t\t\t:deep(.folder) {\n\t\t\t\tmin-width: unset;\n\t\t\t}\n\t\t}\n\t}\n\n\t&__header {\n\t\t&__left {\n\t\t\tdisplay: flex;\n\t\t\tgap: 4px;\n\t\t}\n\t}\n\n\t&__filters {\n\t\tpadding: 16px 64px;\n\t}\n\n\t&__heading {\n\t\tpadding: calc(var(--default-grid-baseline) * 4);\n\t\tmargin-bottom: 0px;\n\t\tpadding-bottom: 0px;\n\t}\n\n\t&__file-list {\n\t\tpadding: 0 64px;\n\n\t\t@media only screen and (max-width: 1200px) {\n\t\t\tpadding: 0 4px;\n\t\t}\n\n\t\t:deep(.files-list-viewer__section-header) {\n\t\t\ttop: var(--photos-navigation-height);\n\t\t}\n\t}\n}\n</style>\n"],"names":["_sfc_main","NcActions","NcCounterBubble","NcVNodes","value","major","newValue","event","navigate","routerLinkHref","e","_sfc_render","_vm","_c","isActive","$event","_sfc_staticRenderFns","__component__","normalizeComponent","NcListItem","_sfc_main$1","defineComponent","Plus","ImageMultipleOutline","NcButton","NcLoadingIcon","NcUserBubble","AlbumForm","fileId","generateUrl","FetchCollectionsMixin","getCurrentUser","albumsExtraProps","album","translate","translatePlural","triggerDownload","url","name","axios","hiddenElement","longestCommonPath","first","second","firstSegments","secondSegments","base","index","segment","downloadFiles","nodes","FileType","node","filenames","DeleteOutline","PlusBoxMultipleOutline","DownloadOutline","Close","FolderAlertOutline","NcEmptyContent","NcModal","NcActionButton","AlbumPicker","FilesListViewer","FileComponent","ActionFavorite","HeaderNavigation","PhotosSourceLocationsSettings","AlertCircleOutline","date","moment","FetchFilesMixin","FilesSelectionMixin","FilesByMonthMixin","to","from","next","key","allMimes","isMobile","useIsMobile","filtersStore","useFilterStore","selectedFilters","filtersQuery","storeToRefs","subscribe","configChangedEvent","unsubscribe","toViewerFileInfo","fileIds","fileid","t"],"mappings":"+jEAKA,MAAMA,GAAY,CAChB,KAAM,aACN,WAAY,CACV,UAAAC,EACA,gBAAAC,EACA,SAAAC,CACD,EACD,MAAO,CAIL,QAAS,CACP,KAAM,OACN,QAAS,EACV,EAID,KAAM,CACJ,KAAM,OACN,QAAS,MACV,EAKD,MAAO,CACL,KAAM,QACN,QAAS,EACV,EAID,GAAI,CACF,KAAM,CAAC,OAAQ,MAAM,EACrB,QAAS,IACV,EAID,KAAM,CACJ,KAAM,OACN,QAAS,GACV,EACD,OAAQ,CACN,KAAM,OACN,QAAS,EACV,EAID,SAAU,CACR,KAAM,OACN,QAAS,EACV,EAID,KAAM,CACJ,KAAM,QACN,QAAS,EACV,EAID,QAAS,CACP,KAAM,QACN,QAAS,EACV,EAID,OAAQ,CACN,KAAM,QACN,QAAS,EACV,EAID,cAAe,CACb,KAAM,OACN,QAAS,EACV,EAID,iBAAkB,CAChB,KAAM,OACN,QAAS,MACV,EAKD,cAAe,CACb,KAAM,CAAC,OAAQ,MAAM,EACrB,QAAS,CACV,EAID,YAAa,CACX,KAAM,OACN,QAAS,GACT,UAAUC,EAAO,CACf,MAAO,CAAC,cAAe,WAAY,EAAE,EAAE,QAAQA,CAAK,IAAM,EAClE,CACK,EAID,oBAAqB,CACnB,KAAM,QACN,QAAS,EACV,EAID,UAAW,CACT,KAAM,QACN,QAAS,EACV,EAID,QAAS,CACP,KAAM,QACN,QAAS,EACf,CACG,EACD,MAAO,CACL,QACA,iBACD,EACD,OAAQ,CACN,KAAM,CAACC,CAAK,EAAI,OAAO,YAAY,QAAQ,MAAM,IAAK,CAAC,GAAK,CAAE,EAE9D,MAAO,CACL,SAFeA,GAAS,OAAO,SAASA,CAAK,EAAI,EAGlD,CACF,EACD,MAAO,CACL,MAAO,CACL,QAAS,GACT,WAAY,GACZ,WAAY,GACZ,2BAA4B,GAC5B,SAAU,GACV,aAAc,GACd,WAAY,EACb,CACF,EACD,SAAU,CACR,wBAAyB,CACvB,MAAO,CAAC,KAAK,4BAA8B,KAAK,mBACjD,EACD,aAAc,CACZ,OAAQ,KAAK,UAAY,IAAM,KAAK,cAAgB,CAAC,KAAK,4BAA8B,KAAK,oBACnG,CACG,EACD,MAAO,CACL,SAASC,EAAU,CACb,CAACA,GAAY,CAAC,KAAK,UACrB,KAAK,2BAA6B,GAE1C,CACG,EACD,SAAU,CACR,KAAK,WAAY,CAClB,EACD,SAAU,CACR,KAAK,WAAY,CAClB,EACD,QAAS,CAQP,QAAQC,EAAOC,EAAUC,EAAgB,CACvC,KAAK,MAAM,QAASF,CAAK,EACrB,EAAAA,EAAM,SAAWA,EAAM,QAAUA,EAAM,SAAWA,EAAM,WAGxDE,IACFD,IAAWD,CAAK,EAChBA,EAAM,eAAgB,EAEzB,EACD,aAAc,CACR,KAAK,aACP,KAAK,2BAA6B,IAEpC,KAAK,QAAU,EAChB,EACD,aAAc,CACZ,KAAK,2BAA6B,EACnC,EAID,WAAWA,EAAO,CACZ,KAAK,UAGL,KAAK,MAAM,WAAW,EAAE,SAASA,EAAM,aAAa,GAGxD,KAAK,YAAa,CACnB,EAID,kBAAmB,CACZ,KAAK,WACR,KAAK,2BAA6B,IAEpC,KAAK,QAAU,EAChB,EACD,iBAAkB,CAChB,KAAK,YAAa,EAClB,KAAK,QAAU,EAChB,EACD,wBAAwBG,EAAG,CACzB,KAAK,SAAWA,EAChB,KAAK,MAAM,kBAAmBA,CAAC,CAChC,EAED,YAAa,CACP,KAAK,aAAe,CAAC,CAAC,KAAK,OAAO,UACpC,KAAK,WAAa,CAAC,CAAC,KAAK,OAAO,SAE9B,KAAK,aAAe,CAAC,CAAC,KAAK,OAAO,UACpC,KAAK,WAAa,CAAC,CAAC,KAAK,OAAO,SAE9B,KAAK,eAAiB,CAAC,CAAC,KAAK,OAAO,YACtC,KAAK,aAAe,CAAC,CAAC,KAAK,OAAO,WAEhC,KAAK,aAAe,CAAC,CAAC,KAAK,OAAO,UACpC,KAAK,WAAa,CAAC,CAAC,KAAK,OAAO,QAExC,CACA,CACA,EACA,IAAIC,GAAc,UAAkB,CAClC,IAAIC,EAAM,KAAMC,EAAKD,EAAI,MAAM,GAC/B,OAAOC,EAAGD,EAAI,GAAK,cAAgB,WAAY,CAAE,IAAK,YAAa,MAAO,CAAE,OAAUA,EAAI,GAAK,GAAO,KAAM,GAAMA,EAAI,GAAI,MAASA,EAAI,GAAKA,EAAI,MAAQ,IAAI,EAAI,YAAaA,EAAI,GAAG,CAAC,CAAE,IAAK,UAAW,GAAI,SAAS,CAAE,KAAMH,EAAgB,SAAAD,EAAU,SAAAM,GAAY,CAChQ,MAAO,CAACD,EAAG,KAAM,CAAE,YAAa,qBAAsB,MAAO,CAAE,6BAA8BC,GAAYF,EAAI,OAAU,EAAE,CAACC,EAAG,MAAO,CAAE,IAAK,YAAa,YAAa,YAAa,MAAO,CACvL,qBAAsBD,EAAI,QAC1B,oBAAqBA,EAAI,SACzB,sBAAuBA,EAAI,OAC5B,EAAE,GAAI,CAAE,UAAaA,EAAI,gBAAiB,WAAcA,EAAI,gBAAkB,CAAA,EAAI,CAACC,EAAG,IAAK,CAAE,YAAa,oBAAqB,MAAO,CAAE,GAAMD,EAAI,UAAY,OAAQ,aAAcA,EAAI,cAAe,KAAQH,GAAkBG,EAAI,KAAM,OAAUA,EAAI,SAAWA,EAAI,OAAS,IAAM,OAAS,UAAW,IAAOA,EAAI,OAAS,IAAM,OAAS,qBAAuB,EAAE,GAAI,CAAE,MAASA,EAAI,YAAa,SAAYA,EAAI,WAAY,MAAS,SAASG,EAAQ,CAC5b,OAAOH,EAAI,QAAQG,EAAQP,EAAUC,CAAc,CACzD,EAAO,QAAW,SAASM,EAAQ,CAC7B,MAAI,CAACA,EAAO,KAAK,QAAQ,KAAK,GAAKH,EAAI,GAAGG,EAAO,QAAS,MAAO,GAAIA,EAAO,IAAK,CAAC,MAAO,QAAQ,CAAC,EAAU,KACrGH,EAAI,YAAY,MAAM,KAAM,SAAS,CAC7C,CAAA,GAAM,CAACA,EAAI,GAAG,MAAM,EAAGC,EAAG,MAAO,CAAE,YAAa,mBAAqB,EAAE,CAACA,EAAG,MAAO,CAAE,YAAa,yBAAyB,EAAI,CAACA,EAAG,MAAO,CAAE,YAAa,yBAA2B,EAAE,CAACD,EAAI,GAAG,OAAQ,UAAW,CAC/M,MAAO,CAACA,EAAI,GAAGA,EAAI,GAAGA,EAAI,IAAI,CAAC,CAAC,CACtC,CAAK,CAAC,EAAG,CAAC,EAAGA,EAAI,WAAaC,EAAG,MAAO,CAAE,YAAa,6BAA8B,MAAO,CAAE,mCAAoCD,EAAI,IAAM,CAAA,EAAI,CAACA,EAAI,GAAG,SAAS,CAAC,EAAG,CAAC,EAAIA,EAAI,GAAI,CAAA,CAAC,EAAGC,EAAG,MAAO,CAAE,YAAa,4BAA4B,EAAI,CAACD,EAAI,YAAcC,EAAG,MAAO,CAAE,YAAa,4BAA8B,EAAE,CAACD,EAAI,GAAG,UAAW,UAAW,CACnV,MAAO,CAACA,EAAI,GAAGA,EAAI,GAAGA,EAAI,OAAO,CAAC,CAAC,CACzC,CAAK,CAAC,EAAG,CAAC,EAAIA,EAAI,KAAMA,EAAI,eAAiBA,EAAI,aAAeC,EAAG,MAAO,CAAE,WAAY,CAAC,CAAE,KAAM,OAAQ,QAAS,SAAU,MAAOD,EAAI,uBAAwB,WAAY,wBAA0B,CAAA,EAAG,YAAa,0BAA0B,EAAI,CAACA,EAAI,cAAgBC,EAAG,kBAAmB,CAAE,YAAa,6BAA8B,MAAO,CAAE,OAAUC,GAAYF,EAAI,OAAQ,KAAQA,EAAI,WAAW,CAAI,EAAE,CAACA,EAAI,GAAG,IAAMA,EAAI,GAAGA,EAAI,aAAa,EAAI,GAAG,CAAC,CAAC,EAAIA,EAAI,GAAE,EAAIA,EAAI,aAAeC,EAAG,OAAQ,CAAE,YAAa,8BAA8B,EAAI,CAACD,EAAI,GAAG,WAAW,CAAC,EAAG,CAAC,EAAIA,EAAI,GAAI,CAAA,EAAG,CAAC,EAAIA,EAAI,IAAI,CAAC,CAAC,CAAC,CAAC,EAAG,CAAC,EAAGA,EAAI,OAAO,eAAe,EAAIC,EAAG,MAAO,CAAE,YAAa,kCAAoC,EAAE,CAACD,EAAI,GAAG,eAAe,CAAC,EAAG,CAAC,EAAIA,EAAI,GAAI,EAAEC,EAAG,MAAO,CAAE,WAAY,CAAC,CAAE,KAAM,OAAQ,QAAS,SAAU,MAAOD,EAAI,qBAAuBA,EAAI,2BAA4B,WAAY,mDAAqD,CAAA,EAAG,YAAa,6BAA8B,GAAI,CAAE,SAAYA,EAAI,UAAU,CAAI,EAAE,CAACC,EAAG,YAAa,CAAE,IAAK,UAAW,MAAO,CAAE,QAAWC,GAAYF,EAAI,OAAQ,aAAcA,EAAI,UAAW,aAAcA,EAAI,gBAAkB,EAAE,GAAI,CAAE,cAAeA,EAAI,uBAAyB,EAAE,YAAaA,EAAI,GAAG,CAACA,EAAI,OAAO,cAAc,EAAI,CAAE,IAAK,OAAQ,GAAI,UAAW,CACxwC,MAAO,CAACA,EAAI,GAAG,cAAc,CAAC,CACpC,EAAO,MAAO,EAAM,EAAG,IAAI,EAAG,KAAM,EAAI,CAAG,EAAE,CAACA,EAAI,GAAG,SAAS,CAAC,EAAG,CAAC,CAAC,EAAG,CAAC,EAAGA,EAAI,OAAO,MAAQC,EAAG,MAAO,CAAE,YAAa,kBAAkB,EAAI,CAACD,EAAI,GAAG,OAAO,CAAC,EAAG,CAAC,EAAIA,EAAI,GAAI,CAAA,CAAC,CAAC,CAAC,CAAC,CAC9K,CAAA,CAAE,EAAG,KAAM,EAAI,EAAG,CACrB,EACII,GAAuB,CAAE,EACzBC,GAAgCC,EAClClB,GACAW,GACAK,GACA,GACA,KACA,UACF,EACA,MAAMG,GAAaF,GAAc,QCjNjCG,GAAAC,EAAA,CACA,KAAA,cAEA,WAAA,CACA,KAAAC,EACA,qBAAAC,EACA,SAAAC,EACA,WAAAL,GACA,cAAAM,EACA,aAAAC,EACA,UAAAC,CACA,EAEA,QAAA,CACA,WAAAC,EAAA,CACA,OAAAC,EAAA,+BAAAD,CAAA,YAAA,CAAA,CAEA,EAEA,OAAA,CAAAE,CAAA,EAEA,MAAA,CACA,MAAA,CACA,sBAAA,EACA,CACA,EAEA,SAAA,CACA,QAAA,CACA,OAAA,KAAA,OAAA,QAAA,MACA,EAEA,cAAA,CACA,OAAA,KAAA,OAAA,QAAA,YACA,EAEA,WAAA,CACA,MAAA,CAAA,GAAA,OAAA,OAAA,KAAA,MAAA,EAAA,GAAA,OAAA,OAAA,KAAA,YAAA,CAAA,CAAA,CAEA,EAEA,SAAA,CACA,KAAA,eAAA,CACA,EAEA,QAAA,CACA,MAAA,gBAAA,CACA,MAAA,KAAA,iBAAA,WAAAC,KAAA,GAAA,UAAAC,CAAA,EACA,MAAA,KAAA,iBAAA,WAAAD,KAAA,GAAA,gBAAAC,CAAA,CACA,EAEA,qBAAA,CACA,KAAA,sBAAA,GACA,KAAA,eAAA,CACA,EAEA,UAAAC,EAAA,CACA,KAAA,MAAA,eAAAA,CAAA,CACA,EAEA,cAAAA,EAAA,CACA,OAAAA,EAAA,KAAA,MAAA,+BAAA,IAAA,IACA,EAEA,aAAAA,EAAA,CACA,OAAA,KAAA,cAAAA,CAAA,EACAA,EAAA,SAAA,QAAA,IAAA,OAAA,MAAAA,EAAA,WAAA,cAAA,CAAA,EAAA,EAAA,MAAA,EAAA,EAAA,EAEAA,EAAA,QAEA,EAEA,EAAAC,EACA,EAAAC,CAAA,CAEA,CAAA,2tDCjIA,eAAeC,EAAgBC,EAAaC,EAAe,CAEpD,MAAAC,EAAM,KAAKF,CAAG,EAEd,MAAAG,EAAgB,SAAS,cAAc,GAAG,EAChDA,EAAc,SAAWF,GAAQ,GACjCE,EAAc,KAAOH,EACrBG,EAAc,MAAM,CACrB,CAQA,SAASC,GAAkBC,EAAeC,EAAwB,CACjE,MAAMC,EAAgBF,EAAM,MAAM,GAAG,EAAE,OAAO,OAAO,EAC/CG,EAAiBF,EAAO,MAAM,GAAG,EAAE,OAAO,OAAO,EACvD,IAAIG,EAAO,GACX,SAAW,CAACC,EAAOC,CAAO,IAAKJ,EAAc,UAAW,CAInD,GAHAG,GAASJ,EAAO,QAGhBK,IAAYH,EAAeE,CAAK,EACnC,MAGDD,EAAO,GAAGA,CAAI,GADFA,IAAS,GAAK,GAAK,GACX,GAAGE,CAAO,EAAA,CAExB,OAAAF,CACR,CAUA,eAAsBG,GAAcC,EAAe,CAC9C,IAAAb,EAEA,GAAAa,EAAM,SAAW,EACpB,GAAIA,EAAM,CAAC,EAAG,OAASC,EAAS,KAAM,CAC/B,MAAAf,EAAgBc,EAAM,CAAC,EAAG,cAAeA,EAAM,CAAC,EAAG,WAAW,EACpE,MAAA,MAEAb,EAAM,IAAI,IAAIa,EAAM,CAAC,EAAG,aAAa,EACjCb,EAAA,aAAa,OAAO,SAAU,KAAK,MAElC,CACNA,EAAM,IAAI,IAAIa,EAAM,CAAC,EAAG,aAAa,EACrC,IAAIJ,EAAOT,EAAI,SACf,UAAWe,KAAQF,EAAM,MAAM,CAAC,EAC/BJ,EAAOL,GAAkBK,EAAO,IAAI,IAAIM,EAAK,aAAa,EAAE,QAAS,EAEtEf,EAAI,SAAWS,EAGf,MAAMO,EAAYH,EAAM,IAAKE,GAAS,mBAAmBA,EAAK,cAAc,MAAMf,EAAI,KAAK,OAAS,CAAC,CAAC,CAAC,EACnGA,EAAA,aAAa,OAAO,SAAU,KAAK,EACvCA,EAAI,aAAa,OAAO,QAAS,KAAK,UAAUgB,CAAS,CAAC,CAAA,CAGvDhB,EAAI,SAAS,GAAG,EAAE,IAAM,MACvBA,EAAA,SAAW,GAAGA,EAAI,QAAQ,KAGzB,MAAAD,EAAgBC,EAAI,IAAI,CAC/B,CCqGA,MAAArC,GAAA,CACA,KAAA,eACA,WAAA,CACA,cAAAsD,EACA,uBAAAC,EACA,gBAAAC,EACA,MAAAC,EACA,KAAAnC,EACA,mBAAAoC,EACA,eAAAC,EACA,QAAAC,EACA,UAAA3D,EACA,eAAA4D,EACA,SAAArC,EACA,UAAAG,EACA,YAAAmC,GACA,gBAAAC,EACA,cAAAC,EACA,eAAAC,EACA,iBAAAC,EACA,8BAAAC,EACA,mBAAAC,CACA,EAEA,QAAA,CACA,UAAAC,EAAA,CACA,OAAAC,EAAAD,EAAA,QAAA,EAAA,OAAA,MAAA,CACA,EAEA,SAAAA,EAAA,CACA,OAAAC,EAAAD,EAAA,QAAA,EAAA,OAAA,MAAA,CAAA,CAEA,EAEA,OAAA,CACAE,EACAC,EACAC,CACA,EAEA,iBAAAC,EAAAC,EAAAC,EAAA,CACA,KAAA,YAAA,SAAA,EAAA,CAAA,EACAA,EAAA,EACA,OAAA,KAAA,KAAA,eAAA,EAAA,QAAAC,GAAA,CACA,KAAA,gBAAAA,CAAA,EAAA,CAAA,CAAA,CACA,CACA,EAEA,MAAA,CACA,cAAA,CACA,KAAA,QACA,QAAA,EACA,EAEA,UAAA,CACA,KAAA,MACA,QAAA,IAAAC,CACA,EAEA,UAAA,CACA,KAAA,QACA,QAAA,EACA,EAEA,UAAA,CACA,KAAA,OACA,SAAA,EAAA,CAEA,EAEA,OAAA,CACA,MAAAC,EAAAC,EAAA,EAEAC,EAAAC,EAAA,EACA,CAAA,gBAAAC,EAAA,aAAAC,GAAAC,EAAAJ,CAAA,EAEA,MAAA,CACA,SAAAF,EACA,gBAAAI,EACA,aAAAC,CACA,CACA,EAEA,MAAA,CACA,MAAA,CACA,aAAA,EACA,sBAAA,GACA,gBAAA,GACA,WAAA,SAAA,eAAA,iBAAA,EACA,YAAA,EACA,CACA,EAEA,SAAA,CACA,OAAA,CACA,OAAA,KAAA,OAAA,MAAA,MAAA,KACA,EAEA,wBAAA,CACA,OAAA,OAAA,KAAA,KAAA,eAAA,EAAA,OAAA,EACA,KAAA,EAAA,SAAA,+BAAA,EAEA,KAAA,EAAA,SAAA,kBAAA,CACA,CAEA,EAEA,MAAA,CACA,cAAA,CACA,KAAA,qBAAA,EACA,KAAA,WAAA,CAAA,CAEA,EAEA,SAAA,CACAE,EAAAC,EAAA,KAAA,sBAAA,CACA,EAEA,WAAA,CACAC,EAAAD,EAAA,KAAA,sBAAA,CACA,EAEA,QAAA,CACA,YAAA,CACA,KAAA,WAAA,CACA,UAAA,KAAA,UACA,UAAA,KAAA,UACA,cAAA,KAAA,cACA,aAAA,KAAA,YAAA,CACA,CACA,EAEA,WAAA3D,EAAA,CACA,OAAA,IAAA,OAAA,KAAA,CACA,SAAA6D,EAAA,KAAA,MAAA7D,CAAA,CAAA,EACA,KAAA,OAAA,OAAA,KAAA,cAAA,EAAA,KAAA,EAAA,IAAAA,GAAA6D,EAAA,KAAA,MAAA7D,CAAA,CAAA,CAAA,CAAA,CACA,CACA,EAEA,cAAA,CAEA,EAEA,MAAA,oBAAAK,EAAA,CACA,KAAA,gBAAA,GACA,MAAA,KAAA,OAAA,SAAA,uBAAA,CAAA,mBAAAA,EAAA,KAAAA,EAAA,KAAA,aAAA,KAAA,gBAAA,CACA,EAEA,MAAA,iBAAA,CAEA,MAAAyD,EAAA,KAAA,gBACA,KAAA,eAAAA,CAAA,EACA,KAAA,eAAA,KAAA,eAAA,OAAAC,GAAA,CAAAD,EAAA,SAAAC,CAAA,CAAA,EACA,MAAA,KAAA,OAAA,SAAA,cAAAD,CAAA,CACA,EAEA,uBAAA,CAAA,IAAAb,GAAA,CACAA,IAAA,uBACA,KAAA,qBAAA,CAEA,EAEA,uBAAA,CAAA,MAAA5C,GAAA,CACA,KAAA,sBAAA,GACA,KAAA,QAAA,KAAA,WAAAA,EAAA,QAAA,EAAA,CACA,EAEA,uBAAA,CACA,MAAAyD,EAAA,KAAA,gBACA,KAAA,eAAAA,CAAA,EACAzC,GAAAyC,EAAA,IAAA9D,GAAA,KAAA,MAAAA,CAAA,CAAA,CAAA,CACA,EAEAgE,EAAAA,CAAA,CAEA","x_google_ignoreList":[0]}