Finetuned DOM observer and detector of the fully-fledged File Explorer view to enable smoother auto-application of custom sorting

This commit is contained in:
SebastianMC 2025-03-31 13:43:08 +02:00
parent e0b7c9bd6d
commit 22992ad421
1 changed files with 45 additions and 21 deletions

View File

@ -78,11 +78,16 @@ type MonkeyAroundUninstaller = () => void
type ContextMenuProvider = (item: MenuItem) => void type ContextMenuProvider = (item: MenuItem) => void
enum FileExplorerStateError { enum FileExplorerState {
DoesNotExist, DoesNotExist = 1,
DeferredView DeferredView
} }
interface FileExplorerStateError {
state: FileExplorerState
fileExplorerInDeferredState?: FileExplorerLeaf
}
type FileExplorerLeafOrError = ValueOrError<FileExplorerLeaf,FileExplorerStateError> type FileExplorerLeafOrError = ValueOrError<FileExplorerLeaf,FileExplorerStateError>
export default class CustomSortPlugin export default class CustomSortPlugin
@ -188,18 +193,23 @@ export default class CustomSortPlugin
if (fileExplorer) { if (fileExplorer) {
if (fileExplorer.isDeferred) { if (fileExplorer.isDeferred) {
return fileExplorerOrError.setError(FileExplorerStateError.DeferredView) return fileExplorerOrError.setError({
state: FileExplorerState.DeferredView,
fileExplorerInDeferredState: fileExplorer
})
} else { } else {
return fileExplorerOrError.setValue(fileExplorer) return fileExplorerOrError.setValue(fileExplorer)
} }
} else { } else {
return fileExplorerOrError.setError(FileExplorerStateError.DoesNotExist) return fileExplorerOrError.setError({
state: FileExplorerState.DoesNotExist
})
} }
} }
checkFileExplorerIsAvailableAndPatchable(logWarning: boolean = true): FileExplorerLeafOrError { checkFileExplorerIsAvailableAndPatchable(logWarning: boolean = true): FileExplorerLeafOrError {
let fileExplorerOrError = this.getFileExplorer() let fileExplorerOrError = this.getFileExplorer()
if (fileExplorerOrError.e === FileExplorerStateError.DeferredView) { if (fileExplorerOrError.e && fileExplorerOrError.e.state === FileExplorerState.DeferredView) {
if (logWarning) { if (logWarning) {
this.logDeferredFileExplorerInfo() this.logDeferredFileExplorerInfo()
} }
@ -687,22 +697,30 @@ export default class CustomSortPlugin
return false return false
} }
setWatcherForDelayedFileExplorerView() { setWatcherForDelayedFileExplorerView(fileExplorerInDeferredState?: FileExplorerLeaf) {
const self = this const self = this
const fullyFledgedFileExplorerElementSelector = () => document.querySelector('[data-type="file-explorer"] .nav-files-container');
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 mutationObserver = new MutationObserver((_, observerInstance) => {
const fullyFledgedFileExplorerElement = fullyFledgedFileExplorerElementSelector(); const fullyFledgedFileExplorerElement = fullyFledgedFileExplorerElementSelector();
if (fullyFledgedFileExplorerElement) { if (fullyFledgedFileExplorerElement) {
observerInstance.disconnect(); observerInstance.disconnect();
self.delayedApplicationOfCustomSorting(true) self.delayedApplicationOfCustomSorting(self.FROM_DOM_WATCHER)
} }
}); });
const workspaceElement = document.querySelector(".workspace");
if (workspaceElement) { mutationObserver.observe(workspaceLeafContentElementParentToObserve, {
mutationObserver.observe(workspaceElement, {
childList: true, childList: true,
subtree: true subtree: false
}); });
} }
} }
@ -710,6 +728,7 @@ export default class CustomSortPlugin
// Entering this method for the first time after initial delay after plugin loaded (via setTimeout()), // 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 // 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 // the File Explorer view gets transformed from delayed view into fully-fledged active view
FROM_DOM_WATCHER: boolean = true
delayedApplicationOfCustomSorting(fromDOMwatcher?: boolean) { delayedApplicationOfCustomSorting(fromDOMwatcher?: boolean) {
if (!this?.isThePluginStillInstalledAndEnabled()) { if (!this?.isThePluginStillInstalledAndEnabled()) {
console.log(`${PLUGIN_ID} v${this.manifest.version} - delayed handler skipped, plugin no longer active.`) console.log(`${PLUGIN_ID} v${this.manifest.version} - delayed handler skipped, plugin no longer active.`)
@ -728,10 +747,15 @@ export default class CustomSortPlugin
// If file explorer is delayed, configure the watcher // If file explorer is delayed, configure the watcher
// NOTE: Do not configure the watcher if the file explorer is not available // NOTE: Do not configure the watcher if the file explorer is not available
let fileExplorerOrError: FileExplorerLeafOrError = this.checkFileExplorerIsAvailableAndPatchable() let fileExplorerOrError: FileExplorerLeafOrError = this.checkFileExplorerIsAvailableAndPatchable()
if (fileExplorerOrError.e === FileExplorerStateError.DeferredView) { if (fileExplorerOrError.e && fileExplorerOrError.e.state === FileExplorerState.DeferredView) {
this.logDeferredFileExplorerWatcherSetupInfo() this.logDeferredFileExplorerWatcherSetupInfo()
this.setWatcherForDelayedFileExplorerView() this.setWatcherForDelayedFileExplorerView(fileExplorerOrError.e.fileExplorerInDeferredState)
} else { // file explorer is available or does not exist } 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) this.switchPluginStateTo(true)
} }
} else { } else {