Skip to content

Commit 07b82d5

Browse files
fix: show filenames on tight space
Signed-off-by: kristian-zendato <kristian.zendato@nextcloud.com>
1 parent 22143d0 commit 07b82d5

6 files changed

Lines changed: 212 additions & 41 deletions

File tree

‎apps/files/src/components/FileEntry.vue‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ import FileEntryCheckbox from './FileEntry/FileEntryCheckbox.vue'
117117
import FileEntryName from './FileEntry/FileEntryName.vue'
118118
import FileEntryPreview from './FileEntry/FileEntryPreview.vue'
119119
import { useFileActions } from '../composables/useFileActions.ts'
120+
import { useFileListLayout } from '../composables/useFileListLayout.ts'
120121
import { useFileListWidth } from '../composables/useFileListWidth.ts'
121122
import { useRouteParameters } from '../composables/useRouteParameters.ts'
122123
import { useActionsMenuStore } from '../store/actionsmenu.ts'
@@ -162,6 +163,7 @@ export default defineComponent({
162163
const renamingStore = useRenamingStore()
163164
const selectionStore = useSelectionStore()
164165
const { isNarrow } = useFileListWidth()
166+
const layout = useFileListLayout()
165167
const {
166168
fileId: currentRouteFileId,
167169
} = useRouteParameters()
@@ -182,6 +184,7 @@ export default defineComponent({
182184
activeView,
183185
currentRouteFileId,
184186
isNarrow,
187+
layout,
185188
186189
activeStore,
187190
actionsMenuStore,
@@ -215,11 +218,10 @@ export default defineComponent({
215218
},
216219
217220
columns() {
218-
// Hide columns if the list is too small
219-
if (this.isNarrow || this.compact) {
221+
if (this.compact) {
220222
return []
221223
}
222-
return this.activeView?.columns || []
224+
return this.layout.columns
223225
},
224226
225227
mime() {

‎apps/files/src/components/FileEntry/FileEntryActions.vue‎

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
135135
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
136136
import ArrowLeftIcon from 'vue-material-design-icons/ArrowLeft.vue'
137137
import CustomElementRender from '../CustomElementRender.vue'
138-
import { useFileListWidth } from '../../composables/useFileListWidth.ts'
138+
import { INLINE_ACTION_WIDTH, reportInlineActionsWidth, useFileListLayout } from '../../composables/useFileListLayout.ts'
139139
import actionsMixins from '../../mixins/actionsMixin.ts'
140140
import { useActiveStore } from '../../store/active.ts'
141141
import { executeAction } from '../../utils/actionUtils.ts'
@@ -178,16 +178,22 @@ export default defineComponent({
178178
setup() {
179179
// The file list is guaranteed to be shown with active view - thus we can set the `loaded` flag
180180
const activeStore = useActiveStore()
181-
const { isNarrow } = useFileListWidth()
181+
const layout = useFileListLayout()
182182
const enabledFileActions = inject<IFileAction[]>('enabledFileActions', [])
183183
return {
184184
activeStore,
185185
enabledFileActions,
186-
isNarrow,
186+
layout,
187187
t,
188188
}
189189
},
190190
191+
data() {
192+
return {
193+
resizeObserver: null as ResizeObserver | null,
194+
}
195+
},
196+
191197
computed: {
192198
isActive() {
193199
return this.activeStore.activeNode?.source === this.source.source
@@ -206,9 +212,9 @@ export default defineComponent({
206212
}
207213
},
208214
209-
// Enabled action that are displayed inline
210-
enabledInlineActions() {
211-
if (this.isNarrow || this.gridMode) {
215+
// Enabled actions that can be displayed inline
216+
inlineCapableActions() {
217+
if (this.gridMode) {
212218
return []
213219
}
214220
return this.enabledFileActions.filter((action) => {
@@ -221,9 +227,17 @@ export default defineComponent({
221227
})
222228
},
223229
230+
// Enabled actions that are displayed inline
231+
enabledInlineActions() {
232+
if (!this.layout.inlineActions) {
233+
return []
234+
}
235+
return this.inlineCapableActions
236+
},
237+
224238
// Enabled action that are displayed inline with a custom render function
225239
enabledRenderActions() {
226-
if (this.gridMode) {
240+
if (!this.layout.inlineActions || this.gridMode) {
227241
return []
228242
}
229243
return this.enabledFileActions.filter((action) => typeof action.renderInline === 'function')
@@ -287,6 +301,10 @@ export default defineComponent({
287301
openedMenu() {
288302
this.openedSubmenu = null
289303
},
304+
305+
inlineCapableActions() {
306+
this.reportInlineActionsWidth()
307+
},
290308
},
291309
292310
created() {
@@ -301,10 +319,39 @@ export default defineComponent({
301319
})
302320
},
303321
322+
mounted() {
323+
if (this.gridMode) {
324+
return
325+
}
326+
// Inline rendered actions (e.g. tags) are rendered asynchronously and change the cell size
327+
this.resizeObserver = new ResizeObserver(() => this.reportInlineActionsWidth())
328+
this.resizeObserver.observe(this.$el)
329+
this.reportInlineActionsWidth()
330+
},
331+
332+
beforeUnmount() {
333+
this.resizeObserver?.disconnect()
334+
},
335+
304336
methods: {
337+
/**
338+
* Report the width needed by the inline actions of this row to the files list layout
339+
*/
340+
reportInlineActionsWidth() {
341+
if (this.gridMode || !this.$el) {
342+
return
343+
}
344+
345+
const renderActionsWidth = [...this.$el.querySelectorAll<HTMLElement>(':scope > .files-list__row-action--inline')]
346+
.filter((element) => element.offsetWidth > 0)
347+
.reduce((total, element) => total + element.offsetWidth + parseFloat(getComputedStyle(element).marginInlineEnd || '0'), 0)
348+
349+
reportInlineActionsWidth(this.inlineCapableActions.length * INLINE_ACTION_WIDTH + renderActionsWidth)
350+
},
351+
305352
actionDisplayName(action: IFileAction) {
306353
try {
307-
if ((this.gridMode || (this.isNarrow && action.inline)) && typeof action.title === 'function') {
354+
if ((this.gridMode || (!this.layout.inlineActions && action.inline)) && typeof action.title === 'function') {
308355
// if an inline action is rendered in the menu for
309356
// lack of space we use the title first if defined
310357
const title = action.title(this.actionContext)

‎apps/files/src/components/FilesListTableFooter.vue‎

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import type { IColumn, INode, IView } from '@nextcloud/files'
5454
import { formatFileSize } from '@nextcloud/files'
5555
import { t } from '@nextcloud/l10n'
5656
import { computed } from 'vue'
57-
import { useFileListWidth } from '../composables/useFileListWidth.ts'
57+
import { useFileListLayout } from '../composables/useFileListLayout.ts'
5858
import { useActiveStore } from '../store/active.ts'
5959
6060
const props = defineProps<{
@@ -78,17 +78,11 @@ const props = defineProps<{
7878
}>()
7979
8080
const activeStore = useActiveStore()
81-
const { isNarrow } = useFileListWidth()
81+
const layout = useFileListLayout()
8282
8383
const currentFolder = computed(() => activeStore.activeFolder)
8484
85-
const columns = computed(() => {
86-
// Hide columns if the list is too small
87-
if (isNarrow.value) {
88-
return []
89-
}
90-
return props.currentView?.columns || []
91-
})
85+
const columns = computed(() => layout.value.columns)
9286
9387
const totalSize = computed(() => {
9488
// If we have the size already, let's use it

‎apps/files/src/components/FilesListTableHeader.vue‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwit
119119
import FilesListTableHeaderActions from './FilesListTableHeaderActions.vue'
120120
import FilesListTableHeaderButton from './FilesListTableHeaderButton.vue'
121121
import { useFilesSorting } from '../composables/filesSorting.ts'
122-
import { useFileListWidth } from '../composables/useFileListWidth.ts'
122+
import { useFileListLayout } from '../composables/useFileListLayout.ts'
123123
import { useRouteParameters } from '../composables/useRouteParameters.ts'
124124
import { useActiveStore } from '../store/active.ts'
125125
import { useFilesStore } from '../store/files.ts'
@@ -168,27 +168,23 @@ export default defineComponent({
168168
const selectionStore = useSelectionStore()
169169
const { directory } = useRouteParameters()
170170
171-
const { isNarrow } = useFileListWidth()
171+
const layout = useFileListLayout()
172172
173173
return {
174174
activeStore,
175175
filesStore,
176176
selectionStore,
177177
178178
directory,
179-
isNarrow,
179+
layout,
180180
181181
...useFilesSorting(),
182182
}
183183
},
184184
185185
computed: {
186186
columns() {
187-
// Hide columns if the list is too small
188-
if (this.isNarrow) {
189-
return []
190-
}
191-
return this.activeStore.activeView?.columns || []
187+
return this.layout.columns
192188
},
193189
194190
dir() {

‎apps/files/src/components/FilesListVirtual.vue‎

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ import { showError } from '@nextcloud/dialogs'
6969
import { FileType, Folder, getSidebar, Permission, View } from '@nextcloud/files'
7070
import { t } from '@nextcloud/l10n'
7171
import { useHotKey } from '@nextcloud/vue/composables/useHotKey'
72-
import { computed, defineComponent } from 'vue'
72+
import { computed, defineComponent, provide, watch } from 'vue'
7373
import FileEntry from './FileEntry.vue'
7474
import FileEntryGrid from './FileEntryGrid.vue'
7575
import FileListFilterChips from './FileListFilter/FileListFilterChips.vue'
@@ -80,6 +80,7 @@ import FilesListTableHeader from './FilesListTableHeader.vue'
8080
import VirtualList from './VirtualList.vue'
8181
import { useEnabledFileActions } from '../composables/useFileActions.ts'
8282
import { useFileListHeaders } from '../composables/useFileListHeaders.ts'
83+
import { FileListLayoutKey, getFileListLayout, resetInlineActionsWidth, useInlineActionsWidth } from '../composables/useFileListLayout.ts'
8384
import { useFileListWidth } from '../composables/useFileListWidth.ts'
8485
import { useRouteParameters } from '../composables/useRouteParameters.ts'
8586
import { useActiveStore } from '../store/active.ts'
@@ -125,20 +126,9 @@ export default defineComponent({
125126
const activeStore = useActiveStore()
126127
const userConfigStore = useUserConfigStore()
127128
128-
const { isNarrow, isWide } = useFileListWidth()
129+
const { width, isNarrow, isWide } = useFileListWidth()
129130
const { fileId, openDetails, openFile } = useRouteParameters()
130131
131-
const isMimeAvailable = computed(() => {
132-
if (!userConfigStore.userConfig.show_mime_column) {
133-
return false
134-
}
135-
if (!isWide.value) {
136-
return false // only show on wide screens
137-
}
138-
return props.nodes
139-
.some((node: INode) => node.mime !== undefined || node.mime !== 'application/octet-stream')
140-
})
141-
142132
const isMtimeAvailable = computed(() => {
143133
// Hide mtime column on narrow screens
144134
if (isNarrow.value) {
@@ -155,6 +145,22 @@ export default defineComponent({
155145
return props.nodes.some((node: INode) => node.size !== undefined)
156146
})
157147
148+
const inlineActionsWidth = useInlineActionsWidth()
149+
watch(() => [props.currentFolder, props.currentView], resetInlineActionsWidth, { immediate: true })
150+
151+
const layout = computed(() => getFileListLayout(width.value, {
152+
inlineActions: true,
153+
mime: userConfigStore.userConfig.show_mime_column
154+
&& isWide.value // only show on wide screens
155+
&& props.nodes.some((node: INode) => node.mime !== undefined || node.mime !== 'application/octet-stream'),
156+
size: isSizeAvailable.value,
157+
mtime: isMtimeAvailable.value,
158+
columns: isNarrow.value ? [] : (props.currentView.columns ?? []),
159+
}, inlineActionsWidth.value))
160+
provide(FileListLayoutKey, layout)
161+
162+
const isMimeAvailable = computed(() => layout.value.mime)
163+
158164
return {
159165
fileId,
160166
headers: useFileListHeaders(),

0 commit comments

Comments
 (0)