From 135913b3336b5f03b95658e84ad2743cfe65a5c2 Mon Sep 17 00:00:00 2001 From: A-F-V Date: Sat, 1 Jul 2023 00:41:13 +0100 Subject: [PATCH] Simplified and correct view attachment logic --- src/components/ObsidianView.tsx | 12 ++++++---- src/components/ViewPluginBase.ts | 39 +++++++++++++++----------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/components/ObsidianView.tsx b/src/components/ObsidianView.tsx index ed8f542..b9add2f 100644 --- a/src/components/ObsidianView.tsx +++ b/src/components/ObsidianView.tsx @@ -2,7 +2,7 @@ import ArcanaPlugin from 'src/main'; import { ItemView } from 'obsidian'; import * as React from 'react'; import * as ReactDOM from 'react-dom'; -import { createRoot } from 'react-dom/client'; +import { Root, createRoot } from 'react-dom/client'; import { ArcanaContext } from 'src/hooks/context'; // The general boiler plate for creating an obsidian view @@ -12,7 +12,7 @@ export class ObsidianView extends ItemView { private viewType: string; private iconName: string; private displayText: string; - private rootUnmount: () => void; + private root: Root | null = null; constructor( leaf: any, @@ -43,9 +43,9 @@ export class ObsidianView extends ItemView { } async onOpen(): Promise { - const root = createRoot(this.containerEl.children[1]); + this.root = createRoot(this.containerEl.children[1]); - root.render( + this.root.render( {React.createElement(this.view)} @@ -55,7 +55,9 @@ export class ObsidianView extends ItemView { } destroy(): void { - ReactDOM.unmountComponentAtNode(this.containerEl.children[1]); + if (this.root) { + this.root.unmount(); + } } async onClose(): Promise { this.destroy(); diff --git a/src/components/ViewPluginBase.ts b/src/components/ViewPluginBase.ts index 1d0554b..e072c2d 100644 --- a/src/components/ViewPluginBase.ts +++ b/src/components/ViewPluginBase.ts @@ -6,8 +6,6 @@ import ArcanaPluginBase from './ArcanaPluginBase'; export default abstract class ViewPluginBase extends ArcanaPluginBase { protected arcana: ArcanaPlugin; private viewType: string; - private leaf: WorkspaceLeaf; - private viewFactory: (leaf: WorkspaceLeaf) => View; constructor( @@ -19,42 +17,41 @@ export default abstract class ViewPluginBase extends ArcanaPluginBase { ) { super(); this.arcana = arcana; + this.viewType = viewType; this.viewFactory = (leaf: WorkspaceLeaf) => { return new ObsidianView(leaf, arcana, viewType, icon, displayText, view); }; } async onload() { - // Register the Carter View on load + // Register the View on load this.arcana.registerView(this.viewType, leaf => this.viewFactory(leaf)); // Render when the layout is ready this.arcana.app.workspace.onLayoutReady(() => { - this.openView(); + this.activateView(); }); } async onunload() { // Close the view - this.closeView(); + await this.closeView(); } - private async openView() { - // Check if it is already open - const views = this.arcana.app.workspace.getLeavesOfType(this.viewType); - if (views.length == 0) { - // Need to first mount - this.leaf = this.arcana.app.workspace.getLeftLeaf(false); // TODO: Abstract this - await this.leaf.setViewState({ - type: this.viewType, - }); - this.arcana.app.workspace.revealLeaf(this.leaf); - } else { - // Already mounted - // Just set as active - this.arcana.app.workspace.revealLeaf(views[0]); - } + private async activateView() { + // First close the view + await this.closeView(); + // If there are already views of this type, don't open a new one + if (this.arcana.app.workspace.getLeavesOfType(this.viewType).length > 0) + return; + // Associate the view with a fresh left leaf + this.arcana.app.workspace.getLeftLeaf(false).setViewState({ + type: this.viewType, + active: true, + }); } + private async closeView() { - this.leaf.detach(); + // Detach the view + this.arcana.app.workspace.detachLeavesOfType(this.viewType); } }