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
19 changes: 18 additions & 1 deletion __tests__/utils/fileSorting.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { Attribute } from '../../lib/files/nodeData'
import type { Attribute } from '../../lib/node/index.ts'

import { ArgumentsType, describe, expect, test } from 'vitest'
import { File, FilesSortingMode, Folder, sortNodes as originalSortNodes } from '../../lib'
Expand Down Expand Up @@ -55,6 +55,23 @@ describe('sortNodes', () => {
expect(sortNodes(array)).toEqual(['a', 'b', 'c'])
})

/**
* Regression test
* Previously we sorted by basename without extension,
* but also trimmed the extension of folders.
*
* @see https://github.com/nextcloud/server/issues/54036
*/
test('Folder names are compared by full length', () => {
const array = [
folder('10.11', 100, 100),
folder('10.10', 500, 100),
folder('10.10.1', 100, 500),
]

expect(sortNodes(array)).toEqual(['10.10', '10.10.1', '10.11'])
})

test('By default favorites are not handled special', () => {
const array = [
file('a', 500, 100),
Expand Down
15 changes: 15 additions & 0 deletions __tests__/utils/sorting.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,21 @@ describe('orderBy', () => {
).toEqual(['2024-01-05', '2024-01-05 Foo', '2024-01-10', '2024-05-01'])
})

test('Numbers with multiple dots are handled correctly', () => {
const array = [
{ text: '2.11' },
{ text: '2.10' },
{ text: '2.10.1' },
] as const

expect(
orderBy(
array,
[(v) => v.text],
).map((v) => v.text),
).toEqual(['2.10', '2.10.1', '2.11'])
})

test('Dates are handled correctly', () => {
const array = [
{ text: 'monday', date: new Date(1716212366 * 1000) },
Expand Down
19 changes: 15 additions & 4 deletions lib/utils/fileSorting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import type { INode } from '../node/node.ts'
import type { SortingOrder } from './sorting.ts'

import { FileType } from '../node/fileType.ts'
import { orderBy } from './sorting.ts'

export enum FilesSortingMode {
Expand Down Expand Up @@ -54,10 +55,20 @@ export function sortNodes(nodes: readonly INode[], options: FilesSortingOptions
}

/**
* Get the basename without any extension
* @param name The filename to extract the basename from
* Get the basename without any extension if the current node is a file
*
* @param node - The node to get the basename of
*/
const basename = (name: string) => name.lastIndexOf('.') > 0 ? name.slice(0, name.lastIndexOf('.')) : name
function basename(node: INode): string {
const name = node.displayname || node.attributes?.displayname || node.basename || ''
if (node.type === FileType.Folder) {
return name
}

return name.lastIndexOf('.') > 0
? name.slice(0, name.lastIndexOf('.'))
: name
}

const identifiers = [
// 1: Sort favorites first if enabled
Expand All @@ -67,7 +78,7 @@ export function sortNodes(nodes: readonly INode[], options: FilesSortingOptions
// 3: Use sorting mode if NOT basename (to be able to use display name too)
...(sortingOptions.sortingMode !== FilesSortingMode.Name ? [(v: INode) => v[sortingOptions.sortingMode] ?? v.attributes[sortingOptions.sortingMode]] : []),
// 4: Use display name if available, fallback to name
(v: INode) => basename(v.displayname || v.attributes?.displayname || v.basename || ''),
(v: INode) => basename(v),
// 5: Finally, use basename if all previous sorting methods failed
(v: INode) => v.basename,
]
Expand Down