-->
<template>
- <tr :class="{'list__row--active': active}" class="list__row" @contextmenu="onRightClick">
+ <tr :class="{'files-list__row--visible': visible, 'files-list__row--active': isActive}"
+ class="list__row"
+ @contextmenu="onRightClick">
+ <!-- Failed indicator -->
<span v-if="source.attributes.failed" class="files-list__row--failed" />
+ <!-- Checkbox -->
<td class="files-list__row-checkbox">
- <NcCheckboxRadioSwitch v-if="active"
+ <NcCheckboxRadioSwitch v-if="visible"
:aria-label="t('files', 'Select the row for {displayName}', { displayName })"
:checked="selectedFiles"
:value="fileid"
:source="source" />
<!-- Menu actions -->
- <NcActions v-if="active"
+ <NcActions v-if="visible"
ref="actionsMenu"
:boundaries-element="getBoundariesElement()"
:container="getBoundariesElement()"
:class="`files-list__row-${currentView?.id}-${column.id}`"
class="files-list__row-column-custom"
@click="openDetailsIfAvailable">
- <CustomElementRender v-if="active"
+ <CustomElementRender v-if="visible"
:current-view="currentView"
:render="column.render"
:source="source" />
},
props: {
- active: {
+ visible: {
type: Boolean,
default: false,
},
return this.currentView?.columns || []
},
- dir() {
+ currentDir() {
// Remove any trailing slash but leave root slash
return (this.$route?.query?.dir || '/').replace(/^(.+)\/$/, '$1')
},
+ currentFileId() {
+ return this.$route.params.fileid || this.$route.query.fileid || null
+ },
fileid() {
return this.source?.fileid?.toString?.()
},
// Enabled action that are displayed inline with a custom render function
enabledRenderActions() {
- if (!this.active) {
+ if (!this.visible) {
return []
}
return this.enabledActions.filter(action => typeof action.renderInline === 'function')
this.renamingStore.newName = newName
},
},
+
+ isActive() {
+ return this.fileid === this.currentFileId
+ },
},
watch: {
source() {
this.resetState()
this.debounceIfNotCached()
- logger.debug('FileEntry source changed', { source: this.source })
},
/**
isRenaming() {
this.startRenaming()
},
+
+ /**
+ * Open the sidebar if the file is active
+ */
+ isActive(active) {
+ const Sidebar = window?.OCA?.Files?.Sidebar
+ if (active && Sidebar && Sidebar.file !== this.source.path) {
+ Sidebar.open(this.source.path)
+ }
+ },
},
/**
// Store the promise to be able to cancel it
this.previewPromise = new CancelablePromise((resolve, reject, onCancel) => {
const img = new Image()
- // If active, load the preview with higher priority
- img.fetchpriority = this.active ? 'high' : 'auto'
+ // If visible, load the preview with higher priority
+ img.fetchpriority = this.visible ? 'high' : 'auto'
img.onload = () => {
this.backgroundImage = `url(${this.previewUrl})`
this.backgroundFailed = false
this.loading = action.id
Vue.set(this.source, '_loading', true)
- const success = await action.exec(this.source, this.currentView, this.dir)
+ const success = await action.exec(this.source, this.currentView, this.currentDir)
// If the action returns null, we stay silent
if (success === null) {
event.preventDefault()
event.stopPropagation()
// Execute the first default action if any
- this.enabledDefaultActions[0].exec(this.source, this.currentView, this.dir)
+ this.enabledDefaultActions[0].exec(this.source, this.currentView, this.currentDir)
}
},
showError(this.t('files', 'Could not rename "{oldName}", it does not exist any more', { oldName }))
return
} else if (error?.response?.status === 412) {
- showError(this.t('files', 'The name "{newName}"" is already used in the folder "{dir}". Please choose a different name.', { newName, dir: this.dir }))
+ showError(this.t('files', 'The name "{newName}"" is already used in the folder "{dir}". Please choose a different name.', { newName, dir: this.currentDir }))
return
}
tr {
&:hover,
&:focus,
- &:active {
+ &:visible {
background-color: var(--color-background-dark);
}
}
},
},
+ mounted() {
+ // Open the sidebar on the file if it's in the url and
+ // we're just loaded the app for the first time.
+ const Sidebar = window?.OCA?.Files?.Sidebar
+ const node = this.nodes.find(node => node.fileid === this.fileId)
+ if (Sidebar && node) {
+ Sidebar.open(node.path)
+ }
+ },
+
methods: {
getFileId(node) {
return node.fileid
}
}
- // Hover state of the row should also change the favorite markers background
- .files-list__row:hover .favorite-marker-icon svg path {
- stroke: var(--color-background-dark);
+ .files-list__row{
+ &:hover, &:focus, &:active, &--active {
+ background-color: var(--color-background-dark);
+ // Hover state of the row should also change the favorite markers background
+ .favorite-marker-icon svg path {
+ stroke: var(--color-background-dark);
+ }
+ }
}
// Entry preview or mime icon
<component :is="dataComponent"
v-for="(item, i) in renderedItems"
:key="i"
- :active="(i >= bufferItems || index <= bufferItems) && (i < shownItems - bufferItems)"
+ :visible="(i >= bufferItems || index <= bufferItems) && (i < shownItems - bufferItems)"
:source="item"
:index="i"
v-bind="extraProps" />
</tbody>
<!-- Footer -->
- <tfoot ref="tfoot" class="files-list__tfoot">
+ <tfoot v-show="isReady" ref="tfoot" class="files-list__tfoot">
<slot name="footer" />
</tfoot>
</table>
bufferItems,
index: this.scrollToIndex,
beforeHeight: 0,
- footerHeight: 0,
headerHeight: 0,
tableHeight: 0,
resizeObserver: null as ResizeObserver | null,
},
computed: {
+ // Wait for measurements to be done before rendering
+ isReady() {
+ return this.tableHeight > 0
+ },
+
startIndex() {
return Math.max(0, this.index - bufferItems)
},
return Math.ceil((this.tableHeight - this.headerHeight) / this.itemHeight) + bufferItems * 2
},
renderedItems(): (File | Folder)[] {
+ if (!this.isReady) {
+ return []
+ }
return this.dataSources.slice(this.startIndex, this.startIndex + this.shownItems)
},
this.resizeObserver = new ResizeObserver(debounce(() => {
this.beforeHeight = before?.clientHeight ?? 0
- this.footerHeight = tfoot?.clientHeight ?? 0
this.headerHeight = thead?.clientHeight ?? 0
this.tableHeight = root?.clientHeight ?? 0
logger.debug('VirtualList resizeObserver updated')