From 1808e99a4e58dd73ffb08192905ae4d027f72aa9 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:27:33 -0300 Subject: [PATCH 1/5] fix(files-list): replace missing ListViewIcon with NcIconSvgWrapper using mdiViewList Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/views/FilesList/FilesList.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/views/FilesList/FilesList.vue b/src/views/FilesList/FilesList.vue index 68e40dfc63..2c8a1a8d4f 100644 --- a/src/views/FilesList/FilesList.vue +++ b/src/views/FilesList/FilesList.vue @@ -31,8 +31,8 @@ variant="tertiary" @click="toggleGridView"> @@ -77,6 +77,7 @@ import HomeSvg from '@mdi/svg/svg/home.svg?raw' import { mdiFolder, mdiViewGrid, + mdiViewList, } from '@mdi/js' import NcAppContent from '@nextcloud/vue/components/NcAppContent' @@ -120,6 +121,7 @@ export default { sidebarStore, mdiFolder, mdiViewGrid, + mdiViewList, } }, data() { From 8575e5b1a92111a221a20c2d29d21289410e4f2f Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:27:33 -0300 Subject: [PATCH 2/5] fix(files-list): prevent status chip text from wrapping vertically Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../FilesList/FileEntry/FileEntryStatus.vue | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/views/FilesList/FileEntry/FileEntryStatus.vue b/src/views/FilesList/FileEntry/FileEntryStatus.vue index d12d574a58..047ed553ed 100644 --- a/src/views/FilesList/FileEntry/FileEntryStatus.vue +++ b/src/views/FilesList/FileEntry/FileEntryStatus.vue @@ -52,25 +52,23 @@ export default { --chip-size: 24px; --chip-radius: 12px; - display: inline-block; + display: inline-flex; + align-items: center; min-height: var(--chip-size); max-width: 100%; - padding: 4px 12px; + padding: 4px 10px; border-radius: var(--chip-radius); line-height: 1.3; text-align: center; - white-space: pre-wrap; - word-wrap: break-word; - overflow-wrap: break-word; - hyphens: auto; + white-space: nowrap; vertical-align: middle; &__text { display: inline-block; max-width: 100%; - white-space: pre-wrap; - word-wrap: break-word; - overflow-wrap: break-word; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } &--error { From 438295e46288284c19f19508e0d3a68673eddd4d Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:27:33 -0300 Subject: [PATCH 3/5] fix(files-list): allow status chip to expand width in grid view mode Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/views/FilesList/FilesListVirtual.vue | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/views/FilesList/FilesListVirtual.vue b/src/views/FilesList/FilesListVirtual.vue index 8598510227..b88335da39 100644 --- a/src/views/FilesList/FilesListVirtual.vue +++ b/src/views/FilesList/FilesListVirtual.vue @@ -581,8 +581,11 @@ tbody.files-list__tbody.files-list__tbody--grid { position: absolute; top: var(--item-padding); inset-inline-end: var(--item-padding); - width: var(--clickable-area); - height: var(--clickable-area); + width: auto; + max-width: calc(var(--row-width) - 2 * var(--item-padding)); + height: auto; + min-height: var(--clickable-area); + justify-content: flex-end; } .files-list__row-signers { From 68f64fb1be57655d62fe0cd4e31f9e6e306b8d73 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:27:34 -0300 Subject: [PATCH 4/5] test(files-list): update grid toggle icon tests and remove obsolete ListViewIcon stub Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/tests/views/FilesList/FilesList.spec.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/tests/views/FilesList/FilesList.spec.ts b/src/tests/views/FilesList/FilesList.spec.ts index 802059efbf..0703bf671a 100644 --- a/src/tests/views/FilesList/FilesList.spec.ts +++ b/src/tests/views/FilesList/FilesList.spec.ts @@ -127,11 +127,6 @@ describe('FilesList.vue rendering rules', () => { mocks: { $route: routeMock, }, - stubs: { - ListViewIcon: { - template: '', - }, - }, }, }) } @@ -145,6 +140,7 @@ describe('FilesList.vue rendering rules', () => { expect(wrapper.vm.mdiFolder).toBeTruthy() expect(wrapper.vm.mdiViewGrid).toBeTruthy() + expect(wrapper.vm.mdiViewList).toBeTruthy() }) it('shows empty-state request action when user can request sign', async () => { @@ -193,4 +189,17 @@ describe('FilesList.vue rendering rules', () => { const iconWithPath = wrapper.findAll('.nc-icon').find((node) => !!node.attributes('data-path')) expect(iconWithPath?.attributes('data-path')).toBe(wrapper.vm.mdiViewGrid) }) + + it('renders list toggle icon path when in grid mode', async () => { + const filesStore = useFilesStore() + const userConfigStore = useUserConfigStore() + vi.spyOn(filesStore, 'getAllFiles').mockResolvedValue({}) + userConfigStore.files_list_grid_view = true + + const wrapper = mountComponent() + await flushPromises() + + const iconWithPath = wrapper.findAll('.nc-icon').find((node) => !!node.attributes('data-path')) + expect(iconWithPath?.attributes('data-path')).toBe(wrapper.vm.mdiViewList) + }) }) From 25a04d5dcd2b97f09b3644da8ec6f65ea69ce1d4 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:27:34 -0300 Subject: [PATCH 5/5] test(files-list): add FileEntryStatus unit tests Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- .../views/FilesList/FileEntryStatus.spec.ts | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/tests/views/FilesList/FileEntryStatus.spec.ts diff --git a/src/tests/views/FilesList/FileEntryStatus.spec.ts b/src/tests/views/FilesList/FileEntryStatus.spec.ts new file mode 100644 index 0000000000..d1e3e90464 --- /dev/null +++ b/src/tests/views/FilesList/FileEntryStatus.spec.ts @@ -0,0 +1,61 @@ +/** + * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { describe, expect, it } from 'vitest' +import { mount } from '@vue/test-utils' + +import FileEntryStatus from '../../../views/FilesList/FileEntry/FileEntryStatus.vue' + +function mountStatus(props: { status: number; statusText: string; signers?: unknown[] }) { + return mount(FileEntryStatus, { + props: { + signers: [], + ...props, + }, + }) +} + +describe('FileEntryStatus.vue', () => { + it('renders nothing when statusText is "none"', () => { + const wrapper = mountStatus({ status: 0, statusText: 'none' }) + expect(wrapper.find('.status-chip').exists()).toBe(false) + }) + + it('renders chip when statusText is not "none"', () => { + const wrapper = mountStatus({ status: 3, statusText: 'Signed' }) + expect(wrapper.find('.status-chip').exists()).toBe(true) + }) + + it('displays the statusText inside the chip', () => { + const wrapper = mountStatus({ status: 3, statusText: 'Signed' }) + expect(wrapper.find('.status-chip__text').text()).toBe('Signed') + }) + + it.each([ + { status: -1, expected: 'status-chip--not-libresign' }, + { status: 0, expected: 'status-chip--draft' }, + { status: 1, expected: 'status-chip--available' }, + { status: 2, expected: 'status-chip--partial' }, + { status: 3, expected: 'status-chip--signed' }, + { status: 4, expected: 'status-chip--deleted' }, + { status: 5, expected: 'status-chip--signing' }, + ])('applies variant class "$expected" for status $status', ({ status, expected }) => { + const wrapper = mountStatus({ status, statusText: 'any' }) + expect(wrapper.find('.status-chip').classes()).toContain(expected) + }) + + it('falls back to draft variant for unknown status', () => { + const wrapper = mountStatus({ status: 99, statusText: 'Unknown' }) + expect(wrapper.find('.status-chip').classes()).toContain('status-chip--draft') + }) + + it('chip does not apply any inline style that would override the nowrap fix', () => { + const wrapper = mountStatus({ status: 3, statusText: 'Signed' }) + const chip = wrapper.find('.status-chip') + // white-space is controlled by scoped CSS (nowrap); no inline style should override it + expect(chip.exists()).toBe(true) + expect(chip.attributes('style')).toBeUndefined() + }) +})