aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_versions/src/views/VersionTab.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_versions/src/views/VersionTab.vue')
-rw-r--r--apps/files_versions/src/views/VersionTab.vue154
1 files changed, 92 insertions, 62 deletions
diff --git a/apps/files_versions/src/views/VersionTab.vue b/apps/files_versions/src/views/VersionTab.vue
index 932e37e8918..a643aef439d 100644
--- a/apps/files_versions/src/views/VersionTab.vue
+++ b/apps/files_versions/src/views/VersionTab.vue
@@ -1,79 +1,90 @@
<!--
- - @copyright 2022 Carl Schwan <carl@carlschwan.eu>
- - @license AGPL-3.0-or-later
- -
- - This program is free software: you can redistribute it and/or modify
- - it under the terms of the GNU Affero General Public License as
- - published by the Free Software Foundation, either version 3 of the
- - License, or (at your option) any later version.
- -
- - This program is distributed in the hope that it will be useful,
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - GNU Affero General Public License for more details.
- -
- - You should have received a copy of the GNU Affero General Public License
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
- -->
+ - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
<template>
- <ul data-files-versions-versions-list>
- <Version v-for="version in orderedVersions"
- :key="version.mtime"
- :can-view="canView"
- :can-compare="canCompare"
- :load-preview="isActive"
- :version="version"
- :file-info="fileInfo"
- :is-current="version.mtime === fileInfo.mtime"
- :is-first-version="version.mtime === initialVersionMtime"
- @click="openVersion"
- @compare="compareVersion"
- @restore="handleRestore"
- @label-update="handleLabelUpdate"
- @delete="handleDelete" />
- </ul>
+ <div class="versions-tab__container">
+ <VirtualScrolling v-slot="{ visibleSections }"
+ :sections="sections"
+ :header-height="0">
+ <ul :aria-label="t('files_versions', 'File versions')" data-files-versions-versions-list>
+ <template v-if="visibleSections.length === 1">
+ <Version v-for="(row) of visibleSections[0].rows"
+ :key="row.items[0].mtime"
+ :can-view="canView"
+ :can-compare="canCompare"
+ :load-preview="isActive"
+ :version="row.items[0]"
+ :file-info="fileInfo"
+ :is-current="row.items[0].mtime === fileInfo.mtime"
+ :is-first-version="row.items[0].mtime === initialVersionMtime"
+ @click="openVersion"
+ @compare="compareVersion"
+ @restore="handleRestore"
+ @label-update-request="handleLabelUpdateRequest(row.items[0])"
+ @delete="handleDelete" />
+ </template>
+ </ul>
+ <NcLoadingIcon v-if="loading" slot="loader" class="files-list-viewer__loader" />
+ </VirtualScrolling>
+ <VersionLabelDialog v-if="editedVersion"
+ :open.sync="showVersionLabelForm"
+ :version-label="editedVersion.label"
+ @label-update="handleLabelUpdate" />
+ </div>
</template>
<script>
import path from 'path'
+import { getCurrentUser } from '@nextcloud/auth'
import { showError, showSuccess } from '@nextcloud/dialogs'
-import isMobile from '@nextcloud/vue/dist/Mixins/isMobile.js'
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
-import { getCurrentUser } from '@nextcloud/auth'
+import { useIsMobile } from '@nextcloud/vue/composables/useIsMobile'
+import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
-import { fetchVersions, deleteVersion, restoreVersion, setVersionLabel } from '../utils/versions.js'
+import { fetchVersions, deleteVersion, restoreVersion, setVersionLabel } from '../utils/versions.ts'
import Version from '../components/Version.vue'
+import VirtualScrolling from '../components/VirtualScrolling.vue'
+import VersionLabelDialog from '../components/VersionLabelDialog.vue'
export default {
name: 'VersionTab',
components: {
Version,
+ VirtualScrolling,
+ VersionLabelDialog,
+ NcLoadingIcon,
},
- mixins: [
- isMobile,
- ],
+
+ setup() {
+ return {
+ isMobile: useIsMobile(),
+ }
+ },
+
data() {
return {
fileInfo: null,
isActive: false,
- /** @type {import('../utils/versions.js').Version[]} */
+ /** @type {import('../utils/versions.ts').Version[]} */
versions: [],
loading: false,
+ showVersionLabelForm: false,
+ editedVersion: null,
}
},
- mounted() {
- subscribe('files_versions:restore:restored', this.fetchVersions)
- },
- beforeUnmount() {
- unsubscribe('files_versions:restore:restored', this.fetchVersions)
- },
computed: {
+ sections() {
+ const rows = this.orderedVersions.map(version => ({ key: version.mtime, height: 68, sectionKey: 'versions', items: [version] }))
+ return [{ key: 'versions', rows, height: 68 * this.orderedVersions.length }]
+ },
+
/**
* Order versions by mtime.
* Put the current version at the top.
*
- * @return {import('../utils/versions.js').Version[]}
+ * @return {import('../utils/versions.ts').Version[]}
*/
orderedVersions() {
return [...this.versions].sort((a, b) => {
@@ -129,6 +140,12 @@ export default {
return !this.isMobile
},
},
+ mounted() {
+ subscribe('files_versions:restore:restored', this.fetchVersions)
+ },
+ beforeUnmount() {
+ unsubscribe('files_versions:restore:restored', this.fetchVersions)
+ },
methods: {
/**
* Update current fileInfo and fetch new data
@@ -163,7 +180,7 @@ export default {
/**
* Handle restored event from Version.vue
*
- * @param {import('../utils/versions.js').Version} version
+ * @param {import('../utils/versions.ts').Version} version The version to restore
*/
async handleRestore(version) {
// Update local copy of fileInfo as rendering depends on it.
@@ -186,7 +203,7 @@ export default {
try {
await restoreVersion(version)
- if (version.label !== '') {
+ if (version.label) {
showSuccess(t('files_versions', `${version.label} restored`))
} else if (version.mtime === this.initialVersionMtime) {
showSuccess(t('files_versions', 'Initial version restored'))
@@ -203,27 +220,36 @@ export default {
/**
* Handle label-updated event from Version.vue
- *
- * @param {import('../utils/versions.js').Version} version
- * @param {string} newName
+ * @param {import('../utils/versions.ts').Version} version The version to update
*/
- async handleLabelUpdate(version, newName) {
- const oldLabel = version.label
- version.label = newName
+ handleLabelUpdateRequest(version) {
+ this.showVersionLabelForm = true
+ this.editedVersion = version
+ },
+
+ /**
+ * Handle label-updated event from Version.vue
+ * @param {string} newLabel The new label
+ */
+ async handleLabelUpdate(newLabel) {
+ const oldLabel = this.editedVersion.label
+ this.editedVersion.label = newLabel
+ this.showVersionLabelForm = false
try {
- await setVersionLabel(version, newName)
+ await setVersionLabel(this.editedVersion, newLabel)
+ this.editedVersion = null
} catch (exception) {
- version.label = oldLabel
- showError(t('files_versions', 'Could not set version name'))
+ this.editedVersion.label = oldLabel
+ showError(this.t('files_versions', 'Could not set version label'))
+ logger.error('Could not set version label', { exception })
}
},
/**
* Handle deleted event from Version.vue
*
- * @param {import('../utils/versions.js').Version} version
- * @param {string} newName
+ * @param {import('../utils/versions.ts').Version} version The version to delete
*/
async handleDelete(version) {
const index = this.versions.indexOf(version)
@@ -251,13 +277,12 @@ export default {
return
}
- // Versions previews are too small for our use case, so we override hasPreview and previewUrl
+ // Versions previews are too small for our use case, so we override previewUrl
// which makes the viewer render the original file.
// We also point to the original filename if the version is the current one.
const versions = this.versions.map(version => ({
...version,
filename: version.mtime === this.fileInfo.mtime ? path.join('files', getCurrentUser()?.uid ?? '', this.fileInfo.path, this.fileInfo.name) : version.filename,
- hasPreview: false,
previewUrl: undefined,
}))
@@ -268,10 +293,15 @@ export default {
},
compareVersion({ version }) {
- const versions = this.versions.map(version => ({ ...version, hasPreview: false, previewUrl: undefined }))
+ const versions = this.versions.map(version => ({ ...version, previewUrl: undefined }))
OCA.Viewer.compare(this.viewerFileInfo, versions.find(v => v.source === version.source))
},
},
}
</script>
+<style lang="scss">
+.versions-tab__container {
+ height: 100%;
+}
+</style>