Unified the way of accessing the FileExplorerView and added a bit more defensive programming in this area. Also added support for deferred monkey-patching of FileExplorerView in case it doesn't succeeds in the initialization sequence

This commit is contained in:
SebastianMC 2022-09-29 19:05:06 +02:00
parent a2126fa888
commit 13f76cc623
1 changed files with 50 additions and 41 deletions

View File

@ -55,6 +55,8 @@ export default class CustomSortPlugin extends Plugin {
sortSpecCache?: SortSpecsCollection | null sortSpecCache?: SortSpecsCollection | null
initialAutoOrManualSortingTriggered: boolean initialAutoOrManualSortingTriggered: boolean
fileExplorerFolderPatched: boolean
showNotice(message: string, timeout?: number) { showNotice(message: string, timeout?: number) {
if (this.settings.notificationsEnabled) { if (this.settings.notificationsEnabled) {
new Notice(message, timeout) new Notice(message, timeout)
@ -133,9 +135,14 @@ export default class CustomSortPlugin extends Plugin {
this.saveSettings() this.saveSettings()
} }
} }
const fileExplorerView: FileExplorerView = this.getFileExplorer() const fileExplorerView: FileExplorerView | undefined = this.getFileExplorer()
if (fileExplorerView) { if (fileExplorerView) {
fileExplorerView.requestSort(); if (!this.fileExplorerFolderPatched) {
this.fileExplorerFolderPatched = this.patchFileExplorerFolder(fileExplorerView);
}
if (this.fileExplorerFolderPatched) {
fileExplorerView.requestSort();
}
} else { } else {
if (iconToSet === ICON_SORT_ENABLED_ACTIVE) { if (iconToSet === ICON_SORT_ENABLED_ACTIVE) {
iconToSet = ICON_SORT_ENABLED_NOT_APPLIED iconToSet = ICON_SORT_ENABLED_NOT_APPLIED
@ -189,7 +196,7 @@ export default class CustomSortPlugin extends Plugin {
this.initialAutoOrManualSortingTriggered = true this.initialAutoOrManualSortingTriggered = true
if (this.sortSpecCache) { // successful read of sorting specifications? if (this.sortSpecCache) { // successful read of sorting specifications?
this.showNotice('Custom sort ON') this.showNotice('Custom sort ON')
const fileExplorerView: FileExplorerView = this.getFileExplorer() const fileExplorerView: FileExplorerView | undefined = this.getFileExplorer()
if (fileExplorerView) { if (fileExplorerView) {
setIcon(this.ribbonIconEl, ICON_SORT_ENABLED_ACTIVE) setIcon(this.ribbonIconEl, ICON_SORT_ENABLED_ACTIVE)
fileExplorerView.requestSort() fileExplorerView.requestSort()
@ -228,55 +235,57 @@ export default class CustomSortPlugin extends Plugin {
initialize() { initialize() {
this.app.workspace.onLayoutReady(() => { this.app.workspace.onLayoutReady(() => {
this.patchFileExplorerFolder(); this.fileExplorerFolderPatched = this.patchFileExplorerFolder();
}) })
} }
// For the idea of monkey-patching credits go to https://github.com/nothingislost/obsidian-bartender // For the idea of monkey-patching credits go to https://github.com/nothingislost/obsidian-bartender
patchFileExplorerFolder() { patchFileExplorerFolder(fileExplorer?: FileExplorerView): boolean {
let plugin = this; let plugin = this;
let leaf = this.app.workspace.getLeaf(true); fileExplorer = fileExplorer ?? this.getFileExplorer()
const fileExplorer = this.app.viewRegistry.viewByType["file-explorer"](leaf) as FileExplorerView; if (fileExplorer) {
// @ts-ignore // @ts-ignore
let tmpFolder = new TFolder(Vault, ""); let tmpFolder = new TFolder(Vault, "");
let Folder = fileExplorer.createFolderDom(tmpFolder).constructor; let Folder = fileExplorer.createFolderDom(tmpFolder).constructor;
const uninstallerOfFolderSortFunctionWrapper: MonkeyAroundUninstaller = around(Folder.prototype, { const uninstallerOfFolderSortFunctionWrapper: MonkeyAroundUninstaller = around(Folder.prototype, {
// TODO: Unit tests, the logic below becomes more and more complex, bugs are captured at run-time... sort(old: any) {
sort(old: any) { return function (...args: any[]) {
return function (...args: any[]) { // quick check for plugin status
// quick check for plugin status if (plugin.settings.suspended) {
if (plugin.settings.suspended) { return old.call(this, ...args);
return old.call(this, ...args); }
}
// if custom sort is not specified, use the UI-selected // if custom sort is not specified, use the UI-selected
const folder: TFolder = this.file const folder: TFolder = this.file
let sortSpec: CustomSortSpec | null | undefined = plugin.sortSpecCache?.sortSpecByPath[folder.path] let sortSpec: CustomSortSpec | null | undefined = plugin.sortSpecCache?.sortSpecByPath[folder.path]
if (sortSpec) { if (sortSpec) {
if (sortSpec.defaultOrder === CustomSortOrder.standardObsidian) { if (sortSpec.defaultOrder === CustomSortOrder.standardObsidian) {
sortSpec = null // A folder is explicitly excluded from custom sorting plugin sortSpec = null // A folder is explicitly excluded from custom sorting plugin
}
} else if (plugin.sortSpecCache?.sortSpecByWildcard) {
// when no sorting spec found directly by folder path, check for wildcard-based match
sortSpec = plugin.sortSpecCache?.sortSpecByWildcard.folderMatch(folder.path)
if (sortSpec?.defaultOrder === CustomSortOrder.standardObsidian) {
sortSpec = null // A folder subtree can be also explicitly excluded from custom sorting plugin
}
} }
} else if (plugin.sortSpecCache?.sortSpecByWildcard) { if (sortSpec) {
// when no sorting spec found directly by folder path, check for wildcard-based match return folderSort.call(this, sortSpec, ...args);
sortSpec = plugin.sortSpecCache?.sortSpecByWildcard.folderMatch(folder.path) } else {
if (sortSpec?.defaultOrder === CustomSortOrder.standardObsidian) { return old.call(this, ...args);
sortSpec = null // A folder subtree can be also explicitly excluded from custom sorting plugin
} }
} };
if (sortSpec) { }
return folderSort.call(this, sortSpec, ...args); })
} else { this.register(uninstallerOfFolderSortFunctionWrapper)
return old.call(this, ...args); return true
} } else {
}; return false
} }
})
this.register(uninstallerOfFolderSortFunctionWrapper)
leaf.detach()
} }
// Credits go to https://github.com/nothingislost/obsidian-bartender // Credits go to https://github.com/nothingislost/obsidian-bartender
getFileExplorer() { getFileExplorer(): FileExplorerView | undefined {
let fileExplorer: FileExplorerView | undefined = this.app.workspace.getLeavesOfType("file-explorer")?.first() let fileExplorer: FileExplorerView | undefined = this.app.workspace.getLeavesOfType("file-explorer")?.first()
?.view as unknown as FileExplorerView; ?.view as unknown as FileExplorerView;
return fileExplorer; return fileExplorer;