Skip to content

Commit 5bb04f4

Browse files
authored
Merge pull request #203 from SebastianMC/202-improve-automatic-initial-application-of-custom-sorting-for-obsidian-deferred-views
202 improve automatic initial application of custom sorting for obsidian deferred views
2 parents 2342b08 + 22992ad commit 5bb04f4

File tree

1 file changed

+76
-11
lines changed

1 file changed

+76
-11
lines changed

src/main.ts

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,16 @@ type MonkeyAroundUninstaller = () => void
7878

7979
type ContextMenuProvider = (item: MenuItem) => void
8080

81-
enum FileExplorerStateError {
82-
DoesNotExist,
81+
enum FileExplorerState {
82+
DoesNotExist = 1,
8383
DeferredView
8484
}
8585

86+
interface FileExplorerStateError {
87+
state: FileExplorerState
88+
fileExplorerInDeferredState?: FileExplorerLeaf
89+
}
90+
8691
type FileExplorerLeafOrError = ValueOrError<FileExplorerLeaf,FileExplorerStateError>
8792

8893
export default class CustomSortPlugin
@@ -188,20 +193,25 @@ export default class CustomSortPlugin
188193

189194
if (fileExplorer) {
190195
if (fileExplorer.isDeferred) {
191-
return fileExplorerOrError.setError(FileExplorerStateError.DeferredView)
196+
return fileExplorerOrError.setError({
197+
state: FileExplorerState.DeferredView,
198+
fileExplorerInDeferredState: fileExplorer
199+
})
192200
} else {
193201
return fileExplorerOrError.setValue(fileExplorer)
194202
}
195203
} else {
196-
return fileExplorerOrError.setError(FileExplorerStateError.DoesNotExist)
204+
return fileExplorerOrError.setError({
205+
state: FileExplorerState.DoesNotExist
206+
})
197207
}
198208
}
199209

200210
checkFileExplorerIsAvailableAndPatchable(logWarning: boolean = true): FileExplorerLeafOrError {
201211
let fileExplorerOrError = this.getFileExplorer()
202-
if (fileExplorerOrError.e === FileExplorerStateError.DeferredView) {
212+
if (fileExplorerOrError.e && fileExplorerOrError.e.state === FileExplorerState.DeferredView) {
203213
if (logWarning) {
204-
this.logWarningFileExplorerDeferred()
214+
this.logDeferredFileExplorerInfo()
205215
}
206216
return fileExplorerOrError
207217
}
@@ -269,12 +279,17 @@ export default class CustomSortPlugin
269279
}
270280
}
271281

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

288+
logDeferredFileExplorerWatcherSetupInfo() {
289+
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`
290+
console.warn(msg)
291+
}
292+
278293
logWarningFileExplorerNotAvailable() {
279294
const msg = `${PLUGIN_ID} v${this.manifest.version}: failed to locate File Explorer. The 'Files' core plugin can be disabled.\n`
280295
+ `Some community plugins can also disable it.\n`
@@ -583,7 +598,7 @@ export default class CustomSortPlugin
583598
const plugin = this
584599
this.app.workspace.onLayoutReady(() => {
585600
setTimeout(() => {
586-
plugin.initialDelayedApplicationOfCustomSorting.apply(this)
601+
plugin.delayedApplicationOfCustomSorting.apply(this)
587602
},
588603
plugin.settings.delayForInitialApplication)
589604
})
@@ -682,7 +697,39 @@ export default class CustomSortPlugin
682697
return false
683698
}
684699

685-
initialDelayedApplicationOfCustomSorting() {
700+
setWatcherForDelayedFileExplorerView(fileExplorerInDeferredState?: FileExplorerLeaf) {
701+
const self = this
702+
703+
let workspaceLeafContentElementParentToObserve: HTMLElement|Element|null|undefined = fileExplorerInDeferredState?.view?.containerEl?.parentElement
704+
if (!workspaceLeafContentElementParentToObserve) {
705+
// Fallback for the case when DOM is not available for deferred file explorer
706+
// (did not happen in practice, but just in case)
707+
workspaceLeafContentElementParentToObserve = document.querySelector(".workspace");
708+
}
709+
if (workspaceLeafContentElementParentToObserve) {
710+
const fullyFledgedFileExplorerElementSelector=
711+
() => workspaceLeafContentElementParentToObserve.querySelector('[data-type="file-explorer"] .nav-files-container');
712+
713+
const mutationObserver = new MutationObserver((_, observerInstance) => {
714+
const fullyFledgedFileExplorerElement = fullyFledgedFileExplorerElementSelector();
715+
if (fullyFledgedFileExplorerElement) {
716+
observerInstance.disconnect();
717+
self.delayedApplicationOfCustomSorting(self.FROM_DOM_WATCHER)
718+
}
719+
});
720+
721+
mutationObserver.observe(workspaceLeafContentElementParentToObserve, {
722+
childList: true,
723+
subtree: false
724+
});
725+
}
726+
}
727+
728+
// Entering this method for the first time after initial delay after plugin loaded (via setTimeout()),
729+
// and if first attempt is unsuccessful, then entering this method again from DOM watcher, when
730+
// the File Explorer view gets transformed from delayed view into fully-fledged active view
731+
FROM_DOM_WATCHER: boolean = true
732+
delayedApplicationOfCustomSorting(fromDOMwatcher?: boolean) {
686733
if (!this?.isThePluginStillInstalledAndEnabled()) {
687734
console.log(`${PLUGIN_ID} v${this.manifest.version} - delayed handler skipped, plugin no longer active.`)
688735
return
@@ -695,7 +742,25 @@ export default class CustomSortPlugin
695742
return
696743
}
697744

698-
this.switchPluginStateTo(true)
745+
if (!fromDOMwatcher) {
746+
// Only for the first delayed invocation:
747+
// If file explorer is delayed, configure the watcher
748+
// NOTE: Do not configure the watcher if the file explorer is not available
749+
let fileExplorerOrError: FileExplorerLeafOrError = this.checkFileExplorerIsAvailableAndPatchable()
750+
if (fileExplorerOrError.e && fileExplorerOrError.e.state === FileExplorerState.DeferredView) {
751+
this.logDeferredFileExplorerWatcherSetupInfo()
752+
this.setWatcherForDelayedFileExplorerView(fileExplorerOrError.e.fileExplorerInDeferredState)
753+
} else if (fileExplorerOrError.e) {
754+
// file explorer other error - does not exist
755+
// force the plugin switch state to report error and show the error icon
756+
this.switchPluginStateTo(true)
757+
}
758+
else { // file explorer is available
759+
this.switchPluginStateTo(true)
760+
}
761+
} else {
762+
this.switchPluginStateTo(true)
763+
}
699764
}
700765

701766
setRibbonIconToEnabled() {

0 commit comments

Comments
 (0)