aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/src/components/FilesListVirtual.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files/src/components/FilesListVirtual.vue')
-rw-r--r--apps/files/src/components/FilesListVirtual.vue137
1 files changed, 88 insertions, 49 deletions
diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue
index 8fdc87b154c..fbf614caede 100644
--- a/apps/files/src/components/FilesListVirtual.vue
+++ b/apps/files/src/components/FilesListVirtual.vue
@@ -21,7 +21,9 @@
</template>
<template v-if="!isNoneSelected" #header-overlay>
- <span class="files-list__selected">{{ t('files', '{count} selected', { count: selectedNodes.length }) }}</span>
+ <span class="files-list__selected">
+ {{ n('files', '{count} selected', '{count} selected', selectedNodes.length, { count: selectedNodes.length }) }}
+ </span>
<FilesListTableHeaderActions :current-view="currentView"
:selected-nodes="selectedNodes" />
</template>
@@ -46,6 +48,11 @@
:nodes="nodes" />
</template>
+ <!-- Body replacement if no files are available -->
+ <template #empty>
+ <slot name="empty" />
+ </template>
+
<!-- Tfoot-->
<template #footer>
<FilesListTableFooter :current-view="currentView"
@@ -63,12 +70,11 @@
import type { UserConfig } from '../types'
import type { Node as NcNode } from '@nextcloud/files'
import type { ComponentPublicInstance, PropType } from 'vue'
-import type { Location } from 'vue-router'
import { Folder, Permission, View, getFileActions, FileType } from '@nextcloud/files'
import { showError } from '@nextcloud/dialogs'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
-import { translate as t } from '@nextcloud/l10n'
+import { n, t } from '@nextcloud/l10n'
import { useHotKey } from '@nextcloud/vue/composables/useHotKey'
import { defineComponent } from 'vue'
@@ -79,6 +85,7 @@ import { useFileListWidth } from '../composables/useFileListWidth.ts'
import { useRouteParameters } from '../composables/useRouteParameters.ts'
import { useSelectionStore } from '../store/selection.js'
import { useUserConfigStore } from '../store/userconfig.ts'
+import logger from '../logger.ts'
import FileEntry from './FileEntry.vue'
import FileEntryGrid from './FileEntryGrid.vue'
@@ -88,7 +95,6 @@ import FilesListTableFooter from './FilesListTableFooter.vue'
import FilesListTableHeader from './FilesListTableHeader.vue'
import FilesListTableHeaderActions from './FilesListTableHeaderActions.vue'
import VirtualList from './VirtualList.vue'
-import logger from '../logger.ts'
export default defineComponent({
name: 'FilesListVirtual',
@@ -140,6 +146,7 @@ export default defineComponent({
selectionStore,
userConfigStore,
+ n,
t,
}
},
@@ -149,7 +156,6 @@ export default defineComponent({
FileEntry,
FileEntryGrid,
scrollToIndex: 0,
- openFileId: null as number|null,
}
},
@@ -214,39 +220,26 @@ export default defineComponent({
isNoneSelected() {
return this.selectedNodes.length === 0
},
+
+ isEmpty() {
+ return this.nodes.length === 0
+ },
},
watch: {
- fileId: {
- handler(fileId) {
- this.scrollToFile(fileId, false)
- },
- immediate: true,
+ // If nodes gets populated and we have a fileId,
+ // an openFile or openDetails, we fire the appropriate actions.
+ isEmpty() {
+ this.handleOpenQueries()
},
-
- openFile: {
- handler(openFile) {
- if (!openFile || !this.fileId) {
- return
- }
-
- this.handleOpenFile(this.fileId)
- },
- immediate: true,
+ fileId() {
+ this.handleOpenQueries()
},
-
- openDetails: {
- handler(openDetails) {
- // wait for scrolling and updating the actions to settle
- this.$nextTick(() => {
- if (!openDetails || !this.fileId) {
- return
- }
-
- this.openSidebarForFile(this.fileId)
- })
- },
- immediate: true,
+ openFile() {
+ this.handleOpenQueries()
+ },
+ openDetails() {
+ this.handleOpenQueries()
},
},
@@ -276,6 +269,33 @@ export default defineComponent({
},
methods: {
+ handleOpenQueries() {
+ // If the list is empty, or we don't have a fileId,
+ // there's nothing to be done.
+ if (this.isEmpty || !this.fileId) {
+ return
+ }
+
+ logger.debug('FilesListVirtual: checking for requested fileId, openFile or openDetails', {
+ nodes: this.nodes,
+ fileId: this.fileId,
+ openFile: this.openFile,
+ openDetails: this.openDetails,
+ })
+
+ if (this.openFile) {
+ this.handleOpenFile(this.fileId)
+ }
+
+ if (this.openDetails) {
+ this.openSidebarForFile(this.fileId)
+ }
+
+ if (this.fileId) {
+ this.scrollToFile(this.fileId, false)
+ }
+ },
+
openSidebarForFile(fileId) {
// Open the sidebar for the given URL fileid
// iif we just loaded the app.
@@ -285,7 +305,7 @@ export default defineComponent({
sidebarAction.exec(node, this.currentView, this.currentFolder.path)
return
}
- logger.error(`Failed to open sidebar on file ${fileId}, file isn't cached yet !`, { fileId, node })
+ logger.warn(`Failed to open sidebar on file ${fileId}, file isn't cached yet !`, { fileId, node })
},
scrollToFile(fileId: number|null, warn = true) {
@@ -301,6 +321,7 @@ export default defineComponent({
}
this.scrollToIndex = Math.max(0, index)
+ logger.debug('Scrolling to file ' + fileId, { fileId, index })
}
},
@@ -312,7 +333,7 @@ export default defineComponent({
delete query.openfile
delete query.opendetails
- this.activeStore.clearActiveNode()
+ this.activeStore.activeNode = undefined
window.OCP.Files.Router.goToRoute(
null,
{ ...this.$route.params, fileid: String(this.currentFolder.fileid ?? '') },
@@ -365,15 +386,13 @@ export default defineComponent({
}
// The file is either a folder or has no default action other than downloading
// in this case we need to open the details instead and remove the route from the history
- const query = this.$route.query
- delete query.openfile
- query.opendetails = ''
-
logger.debug('Ignore `openfile` query and replacing with `opendetails` for ' + node.path, { node })
- await this.$router.replace({
- ...(this.$route as Location),
- query,
- })
+ window.OCP.Files.Router.goToRoute(
+ null,
+ this.$route.params,
+ { ...this.$route.query, openfile: undefined, opendetails: '' },
+ true, // silent update of the URL
+ )
},
onDragOver(event: DragEvent) {
@@ -446,7 +465,7 @@ export default defineComponent({
delete query.openfile
delete query.opendetails
- this.activeStore.setActiveNode(node)
+ this.activeStore.activeNode = node
// Silent update of the URL
window.OCP.Files.Router.goToRoute(
@@ -462,15 +481,17 @@ export default defineComponent({
<style scoped lang="scss">
.files-list {
- --row-height: 55px;
+ --row-height: 44px;
--cell-margin: 14px;
--checkbox-padding: calc((var(--row-height) - var(--checkbox-size)) / 2);
--checkbox-size: 24px;
--clickable-area: var(--default-clickable-area);
- --icon-preview-size: 32px;
+ --icon-preview-size: 24px;
--fixed-block-start-position: var(--default-clickable-area);
+ display: flex;
+ flex-direction: column;
overflow: auto;
height: 100%;
will-change: scroll-position;
@@ -518,6 +539,13 @@ export default defineComponent({
// Hide the table header below the overlay
margin-block-start: calc(-1 * var(--row-height));
}
+
+ // Visually hide the table when there are no files
+ &--hidden {
+ visibility: hidden;
+ z-index: -1;
+ opacity: 0;
+ }
}
.files-list__filters {
@@ -549,6 +577,7 @@ export default defineComponent({
background-color: var(--color-main-background);
border-block-end: 1px solid var(--color-border);
height: var(--row-height);
+ flex: 0 0 var(--row-height);
}
.files-list__thead,
@@ -567,6 +596,16 @@ export default defineComponent({
top: var(--fixed-block-start-position);
}
+ // Empty content
+ .files-list__empty {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ }
+
tr {
position: relative;
display: flex;
@@ -736,8 +775,8 @@ export default defineComponent({
// File and folder overlay
&-overlay {
position: absolute;
- max-height: calc(var(--icon-preview-size) * 0.5);
- max-width: calc(var(--icon-preview-size) * 0.5);
+ max-height: calc(var(--icon-preview-size) * 0.6);
+ max-width: calc(var(--icon-preview-size) * 0.6);
color: var(--color-primary-element-text);
// better alignment with the folder icon
margin-block-start: 2px;
@@ -855,7 +894,7 @@ export default defineComponent({
}
.files-list__row-mtime {
- width: calc(var(--row-height) * 2);
+ width: calc(var(--row-height) * 2.5);
}
.files-list__row-mime {