Skip to content
Merged
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
87 changes: 76 additions & 11 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,16 @@ type MonkeyAroundUninstaller = () => void

type ContextMenuProvider = (item: MenuItem) => void

enum FileExplorerStateError {
DoesNotExist,
enum FileExplorerState {
DoesNotExist = 1,
DeferredView
}

interface FileExplorerStateError {
state: FileExplorerState
fileExplorerInDeferredState?: FileExplorerLeaf
}

type FileExplorerLeafOrError = ValueOrError<FileExplorerLeaf,FileExplorerStateError>

export default class CustomSortPlugin
Expand Down Expand Up @@ -188,20 +193,25 @@ export default class CustomSortPlugin

if (fileExplorer) {
if (fileExplorer.isDeferred) {
return fileExplorerOrError.setError(FileExplorerStateError.DeferredView)
return fileExplorerOrError.setError({
state: FileExplorerState.DeferredView,
fileExplorerInDeferredState: fileExplorer
})
} else {
return fileExplorerOrError.setValue(fileExplorer)
}
} else {
return fileExplorerOrError.setError(FileExplorerStateError.DoesNotExist)
return fileExplorerOrError.setError({
state: FileExplorerState.DoesNotExist
})
}
}

checkFileExplorerIsAvailableAndPatchable(logWarning: boolean = true): FileExplorerLeafOrError {
let fileExplorerOrError = this.getFileExplorer()
if (fileExplorerOrError.e === FileExplorerStateError.DeferredView) {
if (fileExplorerOrError.e && fileExplorerOrError.e.state === FileExplorerState.DeferredView) {
if (logWarning) {
this.logWarningFileExplorerDeferred()
this.logDeferredFileExplorerInfo()
}
return fileExplorerOrError
}
Expand Down Expand Up @@ -269,12 +279,17 @@ export default class CustomSortPlugin
}
}

logWarningFileExplorerDeferred() {
const msg = `${PLUGIN_ID} v${this.manifest.version}: failed to get active File Explorer view.\n`
logDeferredFileExplorerInfo() {
const msg = `${PLUGIN_ID} v${this.manifest.version}: File Explorer is not displayed yet (Obsidian deferred view detected).\n`
+ `Until the File Explorer is visible, the custom-sort plugin cannot apply the custom order.\n`
console.warn(msg)
}

logDeferredFileExplorerWatcherSetupInfo() {
const msg = `${PLUGIN_ID} v${this.manifest.version}: A watcher was set up to apply custom sort automatically when the File Explorer is displayed.\n`
console.warn(msg)
}

logWarningFileExplorerNotAvailable() {
const msg = `${PLUGIN_ID} v${this.manifest.version}: failed to locate File Explorer. The 'Files' core plugin can be disabled.\n`
+ `Some community plugins can also disable it.\n`
Expand Down Expand Up @@ -583,7 +598,7 @@ export default class CustomSortPlugin
const plugin = this
this.app.workspace.onLayoutReady(() => {
setTimeout(() => {
plugin.initialDelayedApplicationOfCustomSorting.apply(this)
plugin.delayedApplicationOfCustomSorting.apply(this)
},
plugin.settings.delayForInitialApplication)
})
Expand Down Expand Up @@ -682,7 +697,39 @@ export default class CustomSortPlugin
return false
}

initialDelayedApplicationOfCustomSorting() {
setWatcherForDelayedFileExplorerView(fileExplorerInDeferredState?: FileExplorerLeaf) {
const self = this

let workspaceLeafContentElementParentToObserve: HTMLElement|Element|null|undefined = fileExplorerInDeferredState?.view?.containerEl?.parentElement
if (!workspaceLeafContentElementParentToObserve) {
// Fallback for the case when DOM is not available for deferred file explorer
// (did not happen in practice, but just in case)
workspaceLeafContentElementParentToObserve = document.querySelector(".workspace");
}
if (workspaceLeafContentElementParentToObserve) {
const fullyFledgedFileExplorerElementSelector=
() => workspaceLeafContentElementParentToObserve.querySelector('[data-type="file-explorer"] .nav-files-container');

const mutationObserver = new MutationObserver((_, observerInstance) => {
const fullyFledgedFileExplorerElement = fullyFledgedFileExplorerElementSelector();
if (fullyFledgedFileExplorerElement) {
observerInstance.disconnect();
self.delayedApplicationOfCustomSorting(self.FROM_DOM_WATCHER)
}
});

mutationObserver.observe(workspaceLeafContentElementParentToObserve, {
childList: true,
subtree: false
});
}
}

// Entering this method for the first time after initial delay after plugin loaded (via setTimeout()),
// and if first attempt is unsuccessful, then entering this method again from DOM watcher, when
// the File Explorer view gets transformed from delayed view into fully-fledged active view
FROM_DOM_WATCHER: boolean = true
delayedApplicationOfCustomSorting(fromDOMwatcher?: boolean) {
if (!this?.isThePluginStillInstalledAndEnabled()) {
console.log(`${PLUGIN_ID} v${this.manifest.version} - delayed handler skipped, plugin no longer active.`)
return
Expand All @@ -695,7 +742,25 @@ export default class CustomSortPlugin
return
}

this.switchPluginStateTo(true)
if (!fromDOMwatcher) {
// Only for the first delayed invocation:
// If file explorer is delayed, configure the watcher
// NOTE: Do not configure the watcher if the file explorer is not available
let fileExplorerOrError: FileExplorerLeafOrError = this.checkFileExplorerIsAvailableAndPatchable()
if (fileExplorerOrError.e && fileExplorerOrError.e.state === FileExplorerState.DeferredView) {
this.logDeferredFileExplorerWatcherSetupInfo()
this.setWatcherForDelayedFileExplorerView(fileExplorerOrError.e.fileExplorerInDeferredState)
} else if (fileExplorerOrError.e) {
// file explorer other error - does not exist
// force the plugin switch state to report error and show the error icon
this.switchPluginStateTo(true)
}
else { // file explorer is available
this.switchPluginStateTo(true)
}
} else {
this.switchPluginStateTo(true)
}
}

setRibbonIconToEnabled() {
Expand Down
Loading