Skip to content

Commit

Permalink
#145 - refactored the plugin integration point and sorting function i…
Browse files Browse the repository at this point in the history
…nvocation and wrapper(s) to work under Obsidian 1.6.0 (which introduced significant refactoring)

Remains to do:
- polish the code to remove duplication in main.js
- full testing under 1.6.0
- regression tests under latest 1.5.x (the code is backward compatible)
  • Loading branch information
SebastianMC committed May 13, 2024
1 parent f5c6484 commit 4ab21d6
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 60 deletions.
51 changes: 33 additions & 18 deletions src/custom-sort/custom-sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -702,21 +702,45 @@ export const determineBookmarksOrderIfNeeded = (folderItems: Array<FolderItemFor
})
}

export const folderSort = function (sortingSpec: CustomSortSpec, ctx: ProcessingContext) {
// This function is a replacement for the Obsidian File Explorer function sort(...) up to Obsidian 1.6.0
// when a major refactoring of sorting mechanics happened
export const folderSort_vUpTo_1_6_0 = function (sortingSpec: CustomSortSpec, ctx: ProcessingContext) {

let fileExplorerView = this.fileExplorer ?? this.view // this.view replaces the former since 1.5.4 insider build
const fileExplorerView = this.fileExplorer ?? this.view // this.view replaces the former since 1.5.4 insider build
const folderUnderSort = this.file as TFolder
const sortOrder = this.sortOrder
const allFileItemsCollection = fileExplorerView.fileItems

const items = folderSortCore(folderUnderSort, sortOrder, sortingSpec, allFileItemsCollection, ctx)

if (requireApiVersion && requireApiVersion("0.15.0")) {
this.vChildren.setChildren(items);
} else {
this.children = items;
}
}

// This function is a replacement for the Obsidian File Explorer function getSortedFolderItems(...)
// which first appeared in Obsidian 1.6.0 and simplified a bit the plugin integration point
export const getSortedFolderItems_vFrom_1_6_0 = function (sortedFolder: TFolder, sortingSpec: CustomSortSpec, ctx: ProcessingContext) {
const sortOrder = this.sortOrder
const allFileItemsCollection = this.fileItems
return folderSortCore(sortedFolder, sortOrder, sortingSpec, allFileItemsCollection, ctx)
}

const folderSortCore = function (sortedFolder: TFolder, sortOrder: string, sortingSpec: CustomSortSpec, allFileItemsCollection: any, ctx: ProcessingContext) {

// shallow copy of groups and expand folder-specific macros on them
sortingSpec.groupsShadow = sortingSpec.groups?.map((group) => Object.assign({} as CustomSortGroup, group))
const parentFolderName: string|undefined = this.file.name
const parentFolderName: string|undefined = sortedFolder.name
expandMacros(sortingSpec, parentFolderName)

const folderItems: Array<FolderItemForSorting> = (sortingSpec.itemsToHide ?
this.file.children.filter((entry: TFile | TFolder) => {
sortedFolder.children.filter((entry: TFile | TFolder) => {
return !sortingSpec.itemsToHide!.has(entry.name)
})
:
this.file.children)
sortedFolder.children)
.map((entry: TFile | TFolder) => {
const itemForSorting: FolderItemForSorting = determineSortingGroup(entry, sortingSpec, ctx)
return itemForSorting
Expand All @@ -729,23 +753,14 @@ export const folderSort = function (sortingSpec: CustomSortSpec, ctx: Processing
determineBookmarksOrderIfNeeded(folderItems, sortingSpec, ctx.bookmarksPluginInstance)
}

const comparator: SorterFn = getComparator(sortingSpec, fileExplorerView.sortOrder)
const comparator: SorterFn = getComparator(sortingSpec, sortOrder)

folderItems.sort(comparator)

const items = folderItems
.map((item: FolderItemForSorting) => fileExplorerView.fileItems[item.path])

if (requireApiVersion && requireApiVersion("0.16.0")) {
const scrollTop = fileExplorerView.navFileContainerEl.scrollTop
fileExplorerView.tree.infinityScroll.rootEl.vChildren.setChildren([items])
fileExplorerView.navFileContainerEl.scrollTop = scrollTop
fileExplorerView.tree.infinityScroll.compute()
} else if (requireApiVersion && requireApiVersion("0.15.0")) {
this.vChildren.setChildren(items);
} else {
this.children = items;
}
.map((item: FolderItemForSorting) => allFileItemsCollection[item.path])

return items
};

// Returns a sorted copy of the input array, intentionally to keep it intact
Expand Down
120 changes: 78 additions & 42 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {
} from 'obsidian';
import {around} from 'monkey-around';
import {
folderSort,
folderSort_vUpTo_1_6_0,
getSortedFolderItems_vFrom_1_6_0,
ObsidianStandardDefaultSortingName,
ProcessingContext,
sortFolderItemsForBookmarking
Expand Down Expand Up @@ -593,51 +594,86 @@ export default class CustomSortPlugin extends Plugin {
// That's why not showing and not logging error message here
patchableFileExplorer = patchableFileExplorer ?? this.checkFileExplorerIsAvailableAndPatchable(false)
if (patchableFileExplorer) {
// @ts-ignore
let tmpFolder = new TFolder(Vault, "");
let Folder = patchableFileExplorer.createFolderDom(tmpFolder).constructor;
const uninstallerOfFolderSortFunctionWrapper: MonkeyAroundUninstaller = around(Folder.prototype, {
sort(old: any) {
return function (...args: any[]) {
// quick check for plugin status
if (plugin.settings.suspended) {
return old.call(this, ...args);
}

if (plugin.ribbonIconStateInaccurate && plugin.ribbonIconEl) {
plugin.ribbonIconStateInaccurate = false
setIcon(plugin.ribbonIconEl, ICON_SORT_ENABLED_ACTIVE)
}
if (requireApiVersion && requireApiVersion("1.6.0")) {
// Starting from Obsidian 1.6.0 the sorting mechanics has been significantly refactored internally in Obsidian
const uninstallerOfFolderSortFunctionWrapper: MonkeyAroundUninstaller = around(patchableFileExplorer.constructor.prototype, {
getSortedFolderItems(old: any) {
return function (...args: any[]) {
// quick check for plugin status
if (plugin.settings.suspended) {
return old.call(this, ...args);
}

if (plugin.ribbonIconStateInaccurate && plugin.ribbonIconEl) {
plugin.ribbonIconStateInaccurate = false
setIcon(plugin.ribbonIconEl, ICON_SORT_ENABLED_ACTIVE)
}

const folder = args[0]
let sortSpec: CustomSortSpec | null | undefined = plugin.determineSortSpecForFolder(folder.path, folder.name)

// Performance optimization
// Primary intention: when the implicit bookmarks integration is enabled, remain on std Obsidian, if no need to involve bookmarks
let has: HasSortingOrGrouping = collectSortingAndGroupingTypes(sortSpec)
if (hasOnlyByBookmarkOrStandardObsidian(has)) {
const bookmarksPlugin: BookmarksPluginInterface|undefined = getBookmarksPlugin(plugin.app, plugin.settings.bookmarksGroupToConsumeAsOrderingReference, false, true)
if ( !bookmarksPlugin?.bookmarksIncludeItemsInFolder(folder.path)) {
sortSpec = null
}
}

if (sortSpec) {
return getSortedFolderItems_vFrom_1_6_0.call(this, folder, sortSpec, plugin.createProcessingContextForSorting(has))
} else {
return old.call(this, ...args);
}
};
}
})
this.register(uninstallerOfFolderSortFunctionWrapper)
return true
} else {
// Up to Obsidian 1.6.0
// @ts-ignore
let tmpFolder = new TFolder(Vault, "");
let Folder = patchableFileExplorer.createFolderDom(tmpFolder).constructor;
const uninstallerOfFolderSortFunctionWrapper: MonkeyAroundUninstaller = around(Folder.prototype, {
sort(old: any) {
return function (...args: any[]) {
// quick check for plugin status
if (plugin.settings.suspended) {
return old.call(this, ...args);
}

const folder: TFolder = this.file
let sortSpec: CustomSortSpec | null | undefined = plugin.determineSortSpecForFolder(folder.path, folder.name)
if (plugin.ribbonIconStateInaccurate && plugin.ribbonIconEl) {
plugin.ribbonIconStateInaccurate = false
setIcon(plugin.ribbonIconEl, ICON_SORT_ENABLED_ACTIVE)
}

// Performance optimization
// Primary intention: when the implicit bookmarks integration is enabled, remain on std Obsidian, if no need to involve bookmarks
let has: HasSortingOrGrouping = collectSortingAndGroupingTypes(sortSpec)
if (hasOnlyByBookmarkOrStandardObsidian(has)) {
const bookmarksPlugin: BookmarksPluginInterface|undefined = getBookmarksPlugin(plugin.app, plugin.settings.bookmarksGroupToConsumeAsOrderingReference, false, true)
if ( !bookmarksPlugin?.bookmarksIncludeItemsInFolder(folder.path)) {
sortSpec = null
const folder: TFolder = this.file
let sortSpec: CustomSortSpec | null | undefined = plugin.determineSortSpecForFolder(folder.path, folder.name)

// Performance optimization
// Primary intention: when the implicit bookmarks integration is enabled, remain on std Obsidian, if no need to involve bookmarks
let has: HasSortingOrGrouping = collectSortingAndGroupingTypes(sortSpec)
if (hasOnlyByBookmarkOrStandardObsidian(has)) {
const bookmarksPlugin: BookmarksPluginInterface | undefined = getBookmarksPlugin(plugin.app, plugin.settings.bookmarksGroupToConsumeAsOrderingReference, false, true)
if (!bookmarksPlugin?.bookmarksIncludeItemsInFolder(folder.path)) {
sortSpec = null
}
}
}

if (sortSpec) {
return folderSort.call(this, sortSpec, plugin.createProcessingContextForSorting(has));
} else {
return old.call(this, ...args);
}
};
},*/
getSortedFolderItems(old: any) {
return function (...args: any[]) {
console.log(`Cuda cuda ${args?.length}`)
return old.call(this, ...args);
};
}
})
this.register(uninstallerOfFolderSortFunctionWrapper)
return true
if (sortSpec) {
return folderSort_vUpTo_1_6_0.call(this, sortSpec, plugin.createProcessingContextForSorting(has));
} else {
return old.call(this, ...args);
}
};
}
})
this.register(uninstallerOfFolderSortFunctionWrapper)
return true
}
} else {
return false
}
Expand Down

0 comments on commit 4ab21d6

Please sign in to comment.