#111 - changed the sorting behavior for items with undefined attributes
- sorting by bookmarks, item w/o bookmark pushed to the bottom in both: asc and desc orders - sorting by metadata, item w/o metadata pushed to the bottom in both, asc and desc orders - sorting by creation or modification date, advanced mode: empty folders (or folders having only folder children) are pushed to the bottom, regardless of asc or desc order
This commit is contained in:
parent
b97209771f
commit
b4d55c8b70
|
@ -1,4 +1,11 @@
|
|||
import {CachedMetadata, MetadataCache, Pos, TFile, TFolder, Vault} from 'obsidian';
|
||||
import {
|
||||
CachedMetadata,
|
||||
MetadataCache,
|
||||
Pos,
|
||||
TFile,
|
||||
TFolder,
|
||||
Vault
|
||||
} from 'obsidian';
|
||||
import {
|
||||
DEFAULT_FOLDER_CTIME,
|
||||
DEFAULT_FOLDER_MTIME,
|
||||
|
@ -10,6 +17,8 @@ import {
|
|||
matchGroupRegex,
|
||||
ProcessingContext,
|
||||
sorterByBookmarkOrder,
|
||||
sorterByFolderCDate,
|
||||
sorterByFolderMDate,
|
||||
sorterByMetadataField,
|
||||
SorterFn
|
||||
} from './custom-sort';
|
||||
|
@ -2791,7 +2800,7 @@ describe('CustomSortOrder.byMetadataFieldAlphabeticalReverse', () => {
|
|||
expect(result2).toBe(EQUAL_OR_UNCOMPARABLE)
|
||||
expect(result3).toBe(EQUAL_OR_UNCOMPARABLE)
|
||||
})
|
||||
it('should put the item with metadata later if the second one has no metadata (reverse order)', () => {
|
||||
it('should put the item with metadata earlier if the second one has no metadata (reverse order)', () => {
|
||||
// given
|
||||
const itemA: Partial<FolderItemForSorting> = {
|
||||
metadataFieldValue: '15',
|
||||
|
@ -2807,8 +2816,8 @@ describe('CustomSortOrder.byMetadataFieldAlphabeticalReverse', () => {
|
|||
const result2: number = sorter(itemB as FolderItemForSorting, itemA as FolderItemForSorting)
|
||||
|
||||
// then
|
||||
expect(result1).toBe(SORT_FIRST_GOES_LATER)
|
||||
expect(result2).toBe(SORT_FIRST_GOES_EARLIER)
|
||||
expect(result1).toBe(SORT_FIRST_GOES_EARLIER)
|
||||
expect(result2).toBe(SORT_FIRST_GOES_LATER)
|
||||
})
|
||||
it('should refrain from comparing if no metadata on both items', () => {
|
||||
// given
|
||||
|
@ -2849,8 +2858,8 @@ describe('sorterByMetadataField', () => {
|
|||
[false,'mmm','mmm',EQUAL_OR_UNCOMPARABLE, 'c', 'c'],
|
||||
[false,'mmm','mmm',EQUAL_OR_UNCOMPARABLE, 'd', 'e'],
|
||||
[false,'mmm','mmm',EQUAL_OR_UNCOMPARABLE, 'e', 'd'],
|
||||
[false,'abc',undefined,1, 'a','a'],
|
||||
[false,undefined,'klm',-1, 'b','b'],
|
||||
[false,'abc',undefined,-1, 'a','a'],
|
||||
[false,undefined,'klm',1, 'b','b'],
|
||||
[false,undefined,undefined,EQUAL_OR_UNCOMPARABLE, 'a','a'],
|
||||
[false,undefined,undefined,EQUAL_OR_UNCOMPARABLE, 'a','b'],
|
||||
[false,undefined,undefined,EQUAL_OR_UNCOMPARABLE, 'd','c'],
|
||||
|
@ -2884,8 +2893,8 @@ describe('sorterByBookmarkOrder', () => {
|
|||
[false,30,30,0, 'c', 'c'], // not possible in reality - each bookmark order is unique by definition - covered for clarity
|
||||
[false,1,1,0, 'd', 'e'], // ------//-----
|
||||
[false,2,2,0, 'e', 'd'], // ------//-----
|
||||
[false,3,undefined,1, 'a','a'],
|
||||
[false,undefined,4,-1, 'b','b'],
|
||||
[false,3,undefined,-1, 'a','a'],
|
||||
[false,undefined,4,1, 'b','b'],
|
||||
[false,undefined,undefined,0, 'a','a'],
|
||||
[false,undefined,undefined,0, 'a','b'],
|
||||
[false,undefined,undefined,0, 'd','c'],
|
||||
|
@ -2902,3 +2911,69 @@ describe('sorterByBookmarkOrder', () => {
|
|||
expect(normalizedResult).toBe(order)
|
||||
})
|
||||
})
|
||||
|
||||
const OLDER_TIME: number = 1000000
|
||||
const NEWER_TIME: number = OLDER_TIME + 1000
|
||||
const EOU: number = EQUAL_OR_UNCOMPARABLE
|
||||
|
||||
describe('sorterByFolderMDate', () => {
|
||||
it.each([
|
||||
[DEFAULT_FOLDER_MTIME, DEFAULT_FOLDER_MTIME, EOU, EOU, EOU, EOU],
|
||||
[OLDER_TIME, OLDER_TIME, EOU, EOU, EOU, EOU],
|
||||
[OLDER_TIME, NEWER_TIME, -1, 1, 1, -1],
|
||||
[DEFAULT_FOLDER_MTIME, NEWER_TIME, 1, -1, 1, -1],
|
||||
[NEWER_TIME, DEFAULT_FOLDER_MTIME, -1, 1, -1, 1]
|
||||
])('comparing %s and %s should return %s (reversed params %s) and %s for reverse order (and %s for reversed order reversed params)',
|
||||
(dateA: number, dateB: number, orderStraight: number, orderStraightRevParams: number, orderReverse: number, orderReverseRevParams: number) => {
|
||||
const sorterFnStraight = sorterByFolderMDate()
|
||||
const sorterFnReverse = sorterByFolderMDate(true)
|
||||
const itemA: Partial<FolderItemForSorting> = {mtime: dateA}
|
||||
const itemB: Partial<FolderItemForSorting> = {mtime: dateB}
|
||||
const resultS1 = sorterFnStraight(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
const resultS2 = sorterFnStraight(itemB as FolderItemForSorting, itemA as FolderItemForSorting)
|
||||
const resultR1 = sorterFnReverse(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
const resultR2 = sorterFnReverse(itemB as FolderItemForSorting, itemA as FolderItemForSorting)
|
||||
|
||||
const normalizedResultS1 = resultS1 < 0 ? -1 : ((resultS1 > 0) ? 1 : resultS1)
|
||||
const normalizedResultS2 = resultS2 < 0 ? -1 : ((resultS2 > 0) ? 1 : resultS2)
|
||||
const normalizedResultR1 = resultR1 < 0 ? -1 : ((resultR1 > 0) ? 1 : resultR1)
|
||||
const normalizedResultR2 = resultR2 < 0 ? -1 : ((resultR2 > 0) ? 1 : resultR2)
|
||||
|
||||
// then
|
||||
expect(normalizedResultS1).toBe(orderStraight)
|
||||
expect(normalizedResultS2).toBe(orderStraightRevParams)
|
||||
expect(normalizedResultR1).toBe(orderReverse)
|
||||
expect(normalizedResultR2).toBe(orderReverseRevParams)
|
||||
})
|
||||
})
|
||||
|
||||
describe('sorterByFolderCDate', () => {
|
||||
it.each([
|
||||
[DEFAULT_FOLDER_CTIME, DEFAULT_FOLDER_CTIME, EOU, EOU, EOU, EOU],
|
||||
[OLDER_TIME, OLDER_TIME, EOU, EOU, EOU, EOU],
|
||||
[OLDER_TIME, NEWER_TIME, -1, 1, 1, -1],
|
||||
[DEFAULT_FOLDER_CTIME, NEWER_TIME, 1, -1, 1, -1],
|
||||
[NEWER_TIME, DEFAULT_FOLDER_CTIME, -1, 1, -1, 1]
|
||||
])('comparing %s and %s should return %s (reversed params %s) and %s for reverse order (and %s for reversed order reversed params)',
|
||||
(dateA: number, dateB: number, orderStraight: number, orderStraightRevParams: number, orderReverse: number, orderReverseRevParams: number) => {
|
||||
const sorterFnStraight = sorterByFolderCDate()
|
||||
const sorterFnReverse = sorterByFolderCDate(true)
|
||||
const itemA: Partial<FolderItemForSorting> = {ctime: dateA}
|
||||
const itemB: Partial<FolderItemForSorting> = {ctime: dateB}
|
||||
const resultS1 = sorterFnStraight(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
const resultS2 = sorterFnStraight(itemB as FolderItemForSorting, itemA as FolderItemForSorting)
|
||||
const resultR1 = sorterFnReverse(itemA as FolderItemForSorting, itemB as FolderItemForSorting)
|
||||
const resultR2 = sorterFnReverse(itemB as FolderItemForSorting, itemA as FolderItemForSorting)
|
||||
|
||||
const normalizedResultS1 = resultS1 < 0 ? -1 : ((resultS1 > 0) ? 1 : resultS1)
|
||||
const normalizedResultS2 = resultS2 < 0 ? -1 : ((resultS2 > 0) ? 1 : resultS2)
|
||||
const normalizedResultR1 = resultR1 < 0 ? -1 : ((resultR1 > 0) ? 1 : resultR1)
|
||||
const normalizedResultR2 = resultR2 < 0 ? -1 : ((resultR2 > 0) ? 1 : resultR2)
|
||||
|
||||
// then
|
||||
expect(normalizedResultS1).toBe(orderStraight)
|
||||
expect(normalizedResultS2).toBe(orderStraightRevParams)
|
||||
expect(normalizedResultR1).toBe(orderReverse)
|
||||
expect(normalizedResultR2).toBe(orderReverseRevParams)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -112,14 +112,14 @@ export const sorterByMetadataField = (reverseOrder?: boolean, trueAlphabetical?:
|
|||
return sortResult
|
||||
}
|
||||
// Item with metadata goes before the w/o metadata
|
||||
if (amdata) return -1
|
||||
if (bmdata) return 1
|
||||
if (amdata) return reverseOrder ? 1 : -1
|
||||
if (bmdata) return reverseOrder ? -1 : 1
|
||||
|
||||
return EQUAL_OR_UNCOMPARABLE
|
||||
}
|
||||
}
|
||||
|
||||
export const sorterByBookmarkOrder:(reverseOrder?: boolean, trueAlphabetical?: boolean) => SorterFn = (reverseOrder: boolean, trueAlphabetical?: boolean) => {
|
||||
export const sorterByBookmarkOrder:(reverseOrder?: boolean, trueAlphabetical?: boolean) => SorterFn = (reverseOrder: boolean) => {
|
||||
return (a: FolderItemForSorting, b: FolderItemForSorting) => {
|
||||
if (reverseOrder) {
|
||||
[a, b] = [b, a]
|
||||
|
@ -129,8 +129,40 @@ export const sorterByBookmarkOrder:(reverseOrder?: boolean, trueAlphabetical?: b
|
|||
return a.bookmarkedIdx - b.bookmarkedIdx
|
||||
}
|
||||
// Item with bookmark order goes before the w/o bookmark info
|
||||
if (a.bookmarkedIdx) return -1
|
||||
if (b.bookmarkedIdx) return 1
|
||||
if (a.bookmarkedIdx) return reverseOrder ? 1 : -1
|
||||
if (b.bookmarkedIdx) return reverseOrder ? -1 : 1
|
||||
|
||||
return EQUAL_OR_UNCOMPARABLE
|
||||
}
|
||||
}
|
||||
|
||||
export const sorterByFolderCDate:(reverseOrder?: boolean) => SorterFn = (reverseOrder?: boolean) => {
|
||||
return (a: FolderItemForSorting, b: FolderItemForSorting) => {
|
||||
if (reverseOrder) {
|
||||
[a, b] = [b, a]
|
||||
}
|
||||
if (a.ctime && b.ctime) {
|
||||
return a.ctime - b.ctime
|
||||
}
|
||||
// Folder with determined ctime always goes before empty folder (=> undetermined ctime)
|
||||
if (a.ctime) return reverseOrder ? 1 : -1
|
||||
if (b.ctime) return reverseOrder ? -1 : 1
|
||||
|
||||
return EQUAL_OR_UNCOMPARABLE
|
||||
}
|
||||
}
|
||||
|
||||
export const sorterByFolderMDate:(reverseOrder?: boolean) => SorterFn = (reverseOrder?: boolean) => {
|
||||
return (a: FolderItemForSorting, b: FolderItemForSorting) => {
|
||||
if (reverseOrder) {
|
||||
[a, b] = [b, a]
|
||||
}
|
||||
if (a.mtime && b.mtime) {
|
||||
return a.mtime - b.mtime
|
||||
}
|
||||
// Folder with determined mtime always goes before empty folder (=> undetermined ctime)
|
||||
if (a.mtime) return reverseOrder ? 1 : -1
|
||||
if (b.mtime) return reverseOrder ? -1 : 1
|
||||
|
||||
return EQUAL_OR_UNCOMPARABLE
|
||||
}
|
||||
|
@ -142,13 +174,13 @@ const Sorters: { [key in CustomSortOrder]: SorterFn } = {
|
|||
[CustomSortOrder.alphabeticalReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorCompare(b.sortString, a.sortString),
|
||||
[CustomSortOrder.trueAlphabeticalReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => CollatorTrueAlphabeticalCompare(b.sortString, a.sortString),
|
||||
[CustomSortOrder.byModifiedTime]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (a.mtime - b.mtime),
|
||||
[CustomSortOrder.byModifiedTimeAdvanced]: (a: FolderItemForSorting, b: FolderItemForSorting) => a.mtime - b.mtime,
|
||||
[CustomSortOrder.byModifiedTimeAdvanced]: sorterByFolderMDate(),
|
||||
[CustomSortOrder.byModifiedTimeReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (b.mtime - a.mtime),
|
||||
[CustomSortOrder.byModifiedTimeReverseAdvanced]: (a: FolderItemForSorting, b: FolderItemForSorting) => b.mtime - a.mtime,
|
||||
[CustomSortOrder.byModifiedTimeReverseAdvanced]: sorterByFolderMDate(true),
|
||||
[CustomSortOrder.byCreatedTime]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (a.ctime - b.ctime),
|
||||
[CustomSortOrder.byCreatedTimeAdvanced]: (a: FolderItemForSorting, b: FolderItemForSorting) => a.ctime - b.ctime,
|
||||
[CustomSortOrder.byCreatedTimeAdvanced]: sorterByFolderCDate(),
|
||||
[CustomSortOrder.byCreatedTimeReverse]: (a: FolderItemForSorting, b: FolderItemForSorting) => (a.isFolder && b.isFolder) ? CollatorCompare(a.sortString, b.sortString) : (b.ctime - a.ctime),
|
||||
[CustomSortOrder.byCreatedTimeReverseAdvanced]: (a: FolderItemForSorting, b: FolderItemForSorting) => b.ctime - a.ctime,
|
||||
[CustomSortOrder.byCreatedTimeReverseAdvanced]: sorterByFolderCDate(true),
|
||||
[CustomSortOrder.byMetadataFieldAlphabetical]: sorterByMetadataField(StraightOrder, !TrueAlphabetical, SortingLevelId.forPrimary),
|
||||
[CustomSortOrder.byMetadataFieldTrueAlphabetical]: sorterByMetadataField(StraightOrder, TrueAlphabetical, SortingLevelId.forPrimary),
|
||||
[CustomSortOrder.byMetadataFieldAlphabeticalReverse]: sorterByMetadataField(ReverseOrder, !TrueAlphabetical, SortingLevelId.forPrimary),
|
||||
|
@ -292,6 +324,8 @@ const isByMetadata = (order: CustomSortOrder | undefined) => {
|
|||
order === CustomSortOrder.byMetadataFieldTrueAlphabetical || order === CustomSortOrder.byMetadataFieldTrueAlphabeticalReverse
|
||||
}
|
||||
|
||||
// IMPORTANT: do not change the value of below constants
|
||||
// It is used in sorter to discern empty folders (thus undetermined dates) from other folders
|
||||
export const DEFAULT_FOLDER_MTIME: number = 0
|
||||
export const DEFAULT_FOLDER_CTIME: number = 0
|
||||
|
||||
|
|
Loading…
Reference in New Issue