@@ -135,7 +135,7 @@ import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
135135import NcLoadingIcon from ' @nextcloud/vue/components/NcLoadingIcon'
136136import ArrowLeftIcon from ' vue-material-design-icons/ArrowLeft.vue'
137137import CustomElementRender from ' ../CustomElementRender.vue'
138- import { useFileListWidth } from ' ../../composables/useFileListWidth .ts'
138+ import { INLINE_ACTION_WIDTH , reportInlineActionsWidth , useFileListLayout } from ' ../../composables/useFileListLayout .ts'
139139import actionsMixins from ' ../../mixins/actionsMixin.ts'
140140import { useActiveStore } from ' ../../store/active.ts'
141141import { 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 )
0 commit comments