diff --git a/src/ExcalidrawView.ts b/src/ExcalidrawView.ts index f97cd9c..701f322 100644 --- a/src/ExcalidrawView.ts +++ b/src/ExcalidrawView.ts @@ -912,6 +912,24 @@ export default class ExcalidrawView extends TextFileView { wheelEvent: (ev:WheelEvent)=>void; clearHoverPreview: Function; + public async forceSave() { + if (this.semaphores.autosaving || this.semaphores.saving) { + new Notice("Force Save aborted because saving is in progress)") + return; + } + if(this.preventReloadResetTimer) { + clearTimeout(this.preventReloadResetTimer); + this.preventReloadResetTimer = null; + } + this.semaphores.preventReload = false; + this.semaphores.forceSaving = true; + await this.save(false, true); + this.plugin.triggerEmbedUpdates(); + this.loadSceneFiles(); + this.semaphores.forceSaving = false; + new Notice("Save successful", 1000); + } + onload() { const apiMissing = Boolean(typeof this.containerEl.onWindowMigrated === "undefined") //@ts-ignore @@ -942,23 +960,7 @@ export default class ExcalidrawView extends TextFileView { this.diskIcon = this.addAction( DISK_ICON_NAME, t("FORCE_SAVE"), - async () => { - if (this.semaphores.autosaving || this.semaphores.saving) { - new Notice("Force Save aborted because saving is in progress)") - return; - } - if(this.preventReloadResetTimer) { - clearTimeout(this.preventReloadResetTimer); - this.preventReloadResetTimer = null; - } - this.semaphores.preventReload = false; - this.semaphores.forceSaving = true; - await this.save(false, true); - this.plugin.triggerEmbedUpdates(); - this.loadSceneFiles(); - this.semaphores.forceSaving = false; - new Notice("Save successful", 1000); - }, + async () => this.forceSave(), ); this.textIsRaw_Element = this.addAction( @@ -1720,6 +1722,9 @@ export default class ExcalidrawView extends TextFileView { //console.log(debug); this.semaphores.dirty = this.file?.path; this.diskIcon.querySelector("svg").addClass("excalidraw-dirty"); + if(this.toolsPanelRef?.current) { + this.toolsPanelRef.current.setDirty(true); + } if(!app.isMobile) { if(requireApiVersion("0.16.0")) { //@ts-ignore @@ -1734,6 +1739,9 @@ export default class ExcalidrawView extends TextFileView { return; } this.semaphores.dirty = null; + if(this.toolsPanelRef?.current) { + this.toolsPanelRef.current.setDirty(false); + } const el = api.getSceneElements(); if (el) { this.previousSceneVersion = this.getSceneVersion(el); diff --git a/src/constants.ts b/src/constants.ts index a86a75b..9ae8923 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -212,8 +212,7 @@ COLOR_NAMES.set("yellow", "#ffff00"); COLOR_NAMES.set("yellowgreen", "#9acd32"); export const DEFAULT_MD_EMBED_CSS = `.snw-reference{display: none;}.excalidraw-md-host{padding:0px 10px}.excalidraw-md-footer{height:5px}foreignObject{background-color:transparent}p{display:block;margin-block-start:1em;margin-block-end:1em;margin-inline-start:0px;margin-inline-end:0px;color:inherit}table,tr,th,td{color:inherit;border:1px solid;border-collapse:collapse;padding:3px}th{font-weight:bold;border-bottom:double;background-color:silver}.copy-code-button{display:none}code[class*=language-],pre[class*=language-]{color:#393a34;font-family:"Consolas","Bitstream Vera Sans Mono","Courier New",Courier,monospace;direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;font-size:.9em;line-height:1.2em;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre>code[class*=language-]{font-size:1em}pre[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,code[class*=language-] ::-moz-selection{background:#C1DEF1}pre[class*=language-]::selection,pre[class*=language-] ::selection,code[class*=language-]::selection,code[class*=language-] ::selection{background:#C1DEF1}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;background-color:#0000001a}:not(pre)>code[class*=language-]{padding:.2em;padding-top:1px;padding-bottom:1px;background:#f8f8f8;border:1px solid #dddddd}.token.comment,.token.prolog,.token.doctype,.token.cdata{color:green;font-style:italic}.token.namespace{opacity:.7}.token.string{color:#a31515}.token.punctuation,.token.operator{color:#393a34}.token.url,.token.symbol,.token.number,.token.boolean,.token.variable,.token.constant,.token.inserted{color:#36acaa}.token.atrule,.token.keyword,.token.attr-value,.language-autohotkey .token.selector,.language-json .token.boolean,.language-json .token.number,code[class*=language-css]{color:#00f}.token.function{color:#393a34}.token.deleted,.language-autohotkey .token.tag{color:#9a050f}.token.selector,.language-autohotkey .token.keyword{color:#00009f}.token.important{color:#e90}.token.important,.token.bold{font-weight:bold}.token.italic{font-style:italic}.token.class-name,.language-json .token.property{color:#2b91af}.token.tag,.token.selector{color:maroon}.token.attr-name,.token.property,.token.regex,.token.entity{color:red}.token.directive.tag .tag{background:#ffff00;color:#393a34}.line-numbers.line-numbers .line-numbers-rows{border-right-color:#a5a5a5}.line-numbers .line-numbers-rows>span:before{color:#2b91af}.line-highlight.line-highlight{background:rgba(193,222,241,.2);background:-webkit-linear-gradient(left,rgba(193,222,241,.2) 70%,rgba(221,222,241,0));background:linear-gradient(to right,rgba(193,222,241,.2) 70%,rgba(221,222,241,0))}blockquote{ font-style:italic;background-color:rgb(46,43,42,0.1);margin:0;margin-left:1em;border-radius:0 4px 4px 0;border:1px solid hsl(0,80%,32%);border-left-width:8px;border-top-width:0px;border-right-width:0px;border-bottom-width:0px;padding:10px 20px;margin-inline-start:30px;margin-inline-end:30px;}`; export const SCRIPTENGINE_ICON = ``; -export const DISK_ICON_NAME = "disk"; -export const DISK_ICON = ``; +export const DISK_ICON_NAME = "save"; export const PNG_ICON_NAME = "save-png"; export const PNG_ICON = ``; export const SVG_ICON_NAME = "save-svg"; diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 7ee6c38..d422433 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -459,4 +459,6 @@ export default { GOTO_FULLSCREEN: "Goto fullscreen mode", EXIT_FULLSCREEN: "Exit fullscreen mode", TOGGLE_FULLSCREEN: "Toggle fullscreen mode", + OPEN_LINK_CLICK: "Navigate to selected element link", + OPEN_LINK_PROPS: "Open markdown-embed properties or open link in new window" }; diff --git a/src/main.ts b/src/main.ts index bdf02c2..6ebfd8b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -25,8 +25,6 @@ import { ICON_NAME, SCRIPTENGINE_ICON, SCRIPTENGINE_ICON_NAME, - DISK_ICON, - DISK_ICON_NAME, PNG_ICON, PNG_ICON_NAME, SVG_ICON, @@ -224,7 +222,6 @@ export default class ExcalidrawPlugin extends Plugin { addIcon(ICON_NAME, EXCALIDRAW_ICON); addIcon(SCRIPTENGINE_ICON_NAME, SCRIPTENGINE_ICON); - addIcon(DISK_ICON_NAME, DISK_ICON); addIcon(PNG_ICON_NAME, PNG_ICON); addIcon(SVG_ICON_NAME, SVG_ICON); diff --git a/src/menu/ActionIcons.tsx b/src/menu/ActionIcons.tsx index 3ff225e..aa93870 100644 --- a/src/menu/ActionIcons.tsx +++ b/src/menu/ActionIcons.tsx @@ -210,6 +210,41 @@ export const ICONS = { ), + openLink: ( + + + + + + + ), + openLinkProperties: ( + + + + + + + ), //fa-brands fa-markdown switchToMarkdown: ( { + return ( + + + + + + ) +} + export const stringToSVG = (svg: string) => { svg = svg .replace(/stroke\s*=\s*['"][^"']*['"]/g,"") .replace(/width\s*=\s*['"][^"']*['"]/g,"") .replace(/height\s*=\s*['"][^"']*['"]/g,"") - .replace(" diff --git a/src/menu/ToolsPanel.tsx b/src/menu/ToolsPanel.tsx index 23f186f..8186fea 100644 --- a/src/menu/ToolsPanel.tsx +++ b/src/menu/ToolsPanel.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import { Notice, TFile } from "obsidian"; import * as React from "react"; import { ActionButton } from "./ActionButton"; -import { ICONS, stringToSVG } from "./ActionIcons"; +import { ICONS, saveIcon, stringToSVG } from "./ActionIcons"; import { SCRIPT_INSTALL_FOLDER, CTRL_OR_CMD } from "../Constants"; import { insertLaTeXToView, search } from "../ExcalidrawAutomate"; import ExcalidrawView, { TextMode } from "../ExcalidrawView"; @@ -29,6 +29,7 @@ export type PanelState = { theme: "dark" | "light"; excalidrawViewMode: boolean; minimized: boolean; + isDirty: boolean; isFullscreen: boolean; isPreviewMode: boolean; scriptIconMap: ScriptIconMap; @@ -60,6 +61,7 @@ export class ToolsPanel extends React.Component { theme: "dark", excalidrawViewMode: false, minimized: false, + isDirty: false, isFullscreen: false, isPreviewMode: true, scriptIconMap: {}, @@ -88,6 +90,14 @@ export class ToolsPanel extends React.Component { }); } + setDirty(isDirty: boolean) { + this.setState(()=> { + return { + isDirty, + }; + }); + } + setExcalidrawViewMode(isViewModeEnabled: boolean) { this.setState(() => { return { @@ -277,15 +287,6 @@ export class ToolsPanel extends React.Component { icon={ICONS.scriptEngine} view={this.props.view} /> - { - search(this.props.view); - }} - icon={ICONS.search} - view={this.props.view} - /> { } view={this.props.view} /> + { + search(this.props.view); + }} + icon={ICONS.search} + view={this.props.view} + /> { icon={ICONS.ocr} view={this.props.view} /> + { + const event = new MouseEvent("click", { + ctrlKey: true, + metaKey: false, + shiftKey: false, + altKey: false, + }); + this.props.view.handleLinkClick(this.props.view, event); + }} + icon={ICONS.openLink} + view={this.props.view} + /> + { + const event = new MouseEvent("click", { + ctrlKey: true, + metaKey: false, + shiftKey: true, + altKey: true, + }); + this.props.view.handleLinkClick(this.props.view, event); + }} + icon={ICONS.openLinkProperties} + view={this.props.view} + /> + { + this.props.view.forceSave(); + }} + icon={saveIcon(this.state.isDirty)} + view={this.props.view} + />
diff --git a/src/ocr/Taskbone.ts b/src/ocr/Taskbone.ts index ba19630..60d905c 100644 --- a/src/ocr/Taskbone.ts +++ b/src/ocr/Taskbone.ts @@ -5,6 +5,7 @@ import {log} from "../utils/Utils" import ExcalidrawView from "../ExcalidrawView" import FrontmatterEditor from "src/utils/Frontmatter"; import { ExcalidrawImageElement } from "@zsviczian/excalidraw/types/element/types"; +import { bindingBorderTest } from "@zsviczian/excalidraw/types/element/collision"; const TASKBONE_URL = "https://api.taskbone.com/"; //"https://excalidraw-preview.onrender.com/"; const TASKBONE_OCR_FN = "execute?id=60f394af-85f6-40bc-9613-5d26dc283cbb"; @@ -60,6 +61,8 @@ export default class Taskbone { return; } + + ea.copyViewElementsToEAforEditing(viewElements); const files = view.getScene().files; viewElements.filter(el=>el.type==="image").forEach((el:ExcalidrawImageElement)=>{ @@ -78,7 +81,15 @@ export default class Taskbone { } } }) - const img = await ea.createPNG(undefined,1,undefined,undefined,view.excalidrawAPI.getAppState().theme,10); + + const bb = ea.getBoundingBox(viewElements); + const size = (bb.width*bb.height); + const minRatio = Math.sqrt(360000/size); + const maxRatio = Math.sqrt(size/4000000); + const scale = minRatio > 1 ? minRatio : (maxRatio > 1 ? 1/maxRatio : 1); + console.log(scale); + + const img = await ea.createPNG(undefined,scale,undefined,undefined,view.excalidrawAPI.getAppState().theme,10); const text = await this.getTextForImage(img); if(text) { fe.setKey("taskbone-ocr",text);