diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index fac1237..fdc2941 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -77,7 +77,6 @@ import { } from "./EmbeddedFileLoader"; import { ScriptInstallPrompt } from "./ScriptInstallPrompt"; import { ObsidianMenu, ToolsPanel } from "./ObsidianMenu"; -import { cleanAppStateForExport } from "@zsviczian/excalidraw/types/appState"; export enum TextMode { parsed, @@ -148,7 +147,7 @@ export default class ExcalidrawView extends TextFileView { public excalidrawRef: React.MutableRefObject = null; public excalidrawAPI: any = null; public excalidrawWrapperRef: React.MutableRefObject = null; - private toolsPanelRef: React.MutableRefObject = null; + public toolsPanelRef: React.MutableRefObject = null; private justLoaded: boolean = false; private preventAutozoomOnLoad: boolean = false; public plugin: ExcalidrawPlugin; @@ -983,10 +982,7 @@ export default class ExcalidrawView extends TextFileView { this.loadSceneFiles(); this.updateContainerSize(null, true); this.setDefaultTrayMode(); - const st = this.excalidrawAPI?.getAppState(); - this.toolsPanelRef?.current?.setTheme(st.theme); - this.toolsPanelRef?.current?.setExcalidrawViewMode(st.viewModeEnabled); - this.toolsPanelRef?.current?.setPreviewMode(this.compatibilityMode ? null : this.textMode === TextMode.parsed); + this.initializeToolsIconPanelAfterLoading(); } else { this.instantiateExcalidraw({ elements: excalidrawData.elements, @@ -1021,6 +1017,16 @@ export default class ExcalidrawView extends TextFileView { .length > 0; } + public initializeToolsIconPanelAfterLoading() { + const st = this.excalidrawAPI?.getAppState(); + const panel = this.toolsPanelRef?.current; + if(!panel) return; + panel.setTheme(st.theme); + panel.setExcalidrawViewMode(st.viewModeEnabled); + panel.setPreviewMode(this.compatibilityMode ? null : this.textMode === TextMode.parsed); + panel.updateScriptIconMap(this.plugin.scriptEngine.scriptIconMap); + } + //Compatibility mode with .excalidraw files canAcceptExtension(extension: string) { return extension == "excalidraw"; @@ -1227,10 +1233,7 @@ export default class ExcalidrawView extends TextFileView { this.setDefaultTrayMode(); this.excalidrawWrapperRef.current.firstElementChild?.focus(); this.addFullscreenchangeEvent(); - const st = api.getAppState(); - this.toolsPanelRef?.current?.setTheme(st.theme); - this.toolsPanelRef?.current?.setExcalidrawViewMode(st.viewModeEnabled); - this.toolsPanelRef?.current?.setPreviewMode(this.compatibilityMode ? null : this.textMode === TextMode.parsed); + this.initializeToolsIconPanelAfterLoading(); }); }, [excalidrawRef]); diff --git a/src/ObsidianMenu.tsx b/src/ObsidianMenu.tsx index a51a01e..ab6836c 100644 --- a/src/ObsidianMenu.tsx +++ b/src/ObsidianMenu.tsx @@ -1,14 +1,18 @@ import { AppState } from "@zsviczian/excalidraw/types/types"; import clsx from "clsx"; -import { zIndex } from "html2canvas/dist/types/css/property-descriptors/z-index"; -import { Notice } from "obsidian"; +import { Notice, TFile } from "obsidian"; import * as React from "react"; +import { SCRIPT_INSTALL_FOLDER } from "./constants"; import { insertLaTeXToView, search } from "./ExcalidrawAutomate"; import ExcalidrawView, { TextMode } from "./ExcalidrawView"; import { t } from "./lang/helpers"; import ExcalidrawPlugin from "./main"; +import { ScriptIconMap } from "./Scripts"; import { getIMGFilename } from "./Utils"; +const dark = ' { minimized: false, isFullscreen: false, isPreviewMode: true, + scriptIconMap: {}, } } + updateScriptIconMap(scriptIconMap:ScriptIconMap) { + this.setState(()=>{ + return {scriptIconMap} + }); + } + setPreviewMode(isPreviewMode: boolean) { this.setState(()=>{ return { @@ -63,7 +75,6 @@ export class ToolsPanel extends React.Component { }) } - setFullscreen(isFullscreen: boolean) { this.setState(()=>{ return { @@ -151,6 +162,7 @@ export class ToolsPanel extends React.Component { } render () { + const downloadedScriptsRoot=`${this.props.view.plugin.settings.scriptFolderPath}/${SCRIPT_INSTALL_FOLDER}/` return (
{ display: this.state.visible && !this.state.excalidrawViewMode ? "block":"none", height: "fit-content", maxHeight: "400px", - zIndex: 3 + zIndex: 3, }} >
{
{ Utility actions
{ search(this.props.view); @@ -244,6 +257,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.search} /> { this.props.view.openAsMarkdown(); @@ -251,6 +265,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.switchToMarkdown} /> { if(this.state.isFullscreen) { @@ -263,6 +278,7 @@ export class ToolsPanel extends React.Component { /> { this.state.isPreviewMode === null ? ( { this.props.view.convertExcalidrawToMD(); @@ -270,6 +286,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.convertFile} />) : ( { if(this.state.isPreviewMode) { @@ -287,6 +304,7 @@ export class ToolsPanel extends React.Component { Export actions
{ this.props.view.plugin.exportLibrary(); @@ -294,6 +312,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.exportLibrary} /> { this.props.view.saveSVG(); @@ -302,6 +321,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.exportSVG} /> { this.props.view.savePNG(); @@ -310,6 +330,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.exportPNG} /> { this.props.view.exportExcalidraw(); @@ -322,6 +343,7 @@ export class ToolsPanel extends React.Component { Insert actions
{ this.props.centerPointer(); @@ -331,6 +353,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.insertImage} /> { this.props.centerPointer(); @@ -340,6 +363,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.insertMD} /> { this.props.centerPointer(); @@ -348,6 +372,7 @@ export class ToolsPanel extends React.Component { icon={ICONS.insertLaTeX} /> { this.props.centerPointer(); @@ -360,6 +385,72 @@ export class ToolsPanel extends React.Component { />
+ {this.state.scriptIconMap !== {} && + Object.keys(this.state.scriptIconMap).filter(k=>!k.startsWith(downloadedScriptsRoot)).length !== 0 + ? (
+ User Scripts +
+ {Object.keys(this.state.scriptIconMap) + .filter(k=>!k.startsWith(downloadedScriptsRoot)) + .sort() + .map((key:string) => + { + const f = this.props.view.app.vault.getAbstractFileByPath(key); + if(f && f instanceof TFile) { + this.props.view.plugin.scriptEngine.executeScript(this.props.view,f); + } + }} + icon={this.state.scriptIconMap[key].iconBase64 + ? + : ICONS.cog} + /> + )} +
+
) + : "" + } + {this.state.scriptIconMap !== {} && + Object.keys(this.state.scriptIconMap).filter(k=>k.startsWith(downloadedScriptsRoot)).length !== 0 + ? (
+ Downloaded Scripts +
+ {Object.keys(this.state.scriptIconMap) + .filter(k=>k.startsWith(downloadedScriptsRoot)) + .sort() + .map((key:string) => + { + const f = this.props.view.app.vault.getAbstractFileByPath(key); + if(f && f instanceof TFile) { + this.props.view.plugin.scriptEngine.executeScript(this.props.view,f); + } + }} + icon={this.state.scriptIconMap[key].iconBase64 + ? + : ICONS.cog} + /> + )} +
+
) + : "" + }
@@ -372,6 +463,7 @@ type ButtonProps = { title: string; action: Function; icon: JSX.Element; + key: string; } type ButtonState = { @@ -389,11 +481,16 @@ class ActionButton extends React.Component { render() { return (