Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion apps/files/src/components/FilesListHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import type { Folder, Header, View } from '@nextcloud/files'
import type { PropType } from 'vue'

import logger from '../logger.ts'

/**
* This component is used to render custom
* elements provided by an API. Vue doesn't allow
Expand Down Expand Up @@ -51,8 +53,12 @@ export default {
},
},
mounted() {
console.debug('Mounted', this.header.id)
logger.debug(`Mounted ${this.header.id} FilesListHeader`, { header: this.header })
this.header.render(this.$refs.mount as HTMLElement, this.currentFolder, this.currentView)
},

destroyed() {
logger.debug(`Destroyed ${this.header.id} FilesListHeader`, { header: this.header })
},
}
</script>
115 changes: 75 additions & 40 deletions apps/files/src/components/FilesListVirtual.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,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"
Expand All @@ -65,7 +70,6 @@
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'
Expand All @@ -81,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'
Expand All @@ -90,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',
Expand Down Expand Up @@ -152,7 +156,6 @@ export default defineComponent({
FileEntry,
FileEntryGrid,
scrollToIndex: 0,
openFileId: null as number|null,
}
},

Expand Down Expand Up @@ -217,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()
},
},

Expand Down Expand Up @@ -279,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.
Expand All @@ -288,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) {
Expand All @@ -304,6 +321,7 @@ export default defineComponent({
}

this.scrollToIndex = Math.max(0, index)
logger.debug('Scrolling to file ' + fileId, { fileId, index })
}
},

Expand Down Expand Up @@ -368,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) {
Expand Down Expand Up @@ -474,6 +490,8 @@ export default defineComponent({
--icon-preview-size: 32px;

--fixed-block-start-position: var(--default-clickable-area);
display: flex;
flex-direction: column;
overflow: auto;
height: 100%;
will-change: scroll-position;
Expand Down Expand Up @@ -521,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 {
Expand Down Expand Up @@ -570,6 +595,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;
Expand Down
15 changes: 13 additions & 2 deletions apps/files/src/components/VirtualList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,18 @@
<slot name="header-overlay" />
</div>

<table class="files-list__table" :class="{ 'files-list__table--with-thead-overlay': !!$scopedSlots['header-overlay'] }">
<div v-if="dataSources.length === 0"
class="files-list__empty">
<slot name="empty" />
</div>

<table :aria-hidden="dataSources.length === 0"
:inert="dataSources.length === 0"
class="files-list__table"
:class="{
'files-list__table--with-thead-overlay': !!$scopedSlots['header-overlay'],
'files-list__table--hidden': dataSources.length === 0,
}">
<!-- Accessibility table caption for screen readers -->
<caption v-if="caption" class="hidden-visually">
{{ caption }}
Expand Down Expand Up @@ -309,7 +320,7 @@ export default defineComponent({

methods: {
scrollTo(index: number) {
if (!this.$el) {
if (!this.$el || this.index === index) {
return
}

Expand Down
Loading
Loading