← Back
Editing: TimelineView-Bzb4Tj8Y.chunk.mjs.map
{"version":3,"file":"TimelineView-Bzb4Tj8Y.chunk.mjs","sources":["../src/components/Albums/AlbumPicker.vue","../src/services/downloadFiles.ts","../src/views/TimelineView.vue"],"sourcesContent":["<!--\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') }} <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\tvariant=\"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\tpath=\"/\"\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\tvariant=\"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 }\">\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@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$1","defineComponent","Plus","ImageMultipleOutline","NcButton","NcListItem","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","_sfc_main","DeleteOutline","PlusBoxMultipleOutline","DownloadOutline","Close","FolderAlertOutline","NcEmptyContent","NcModal","NcActions","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":"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"}
Save File
Cancel