mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
Compare commits
6 Commits
2.5.0-beta
...
2.5.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c91186ed5 | ||
|
|
904bc7c994 | ||
|
|
9fd4ae2615 | ||
|
|
18fbb0934e | ||
|
|
3ae59c85d2 | ||
|
|
55db9b0ddb |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "2.5.0-beta-2",
|
||||
"version": "2.5.0-beta-4",
|
||||
"minAppVersion": "1.1.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@zsviczian/excalidraw": "0.17.1-obsidian-51",
|
||||
"@zsviczian/excalidraw": "0.17.1-obsidian-52",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clsx": "^2.0.0",
|
||||
"@zsviczian/colormaster": "^1.2.2",
|
||||
|
||||
@@ -21,7 +21,6 @@ import { ExcalidrawData, getMarkdownDrawingSection, REGEX_LINK } from "src/Excal
|
||||
import {
|
||||
FRONTMATTER,
|
||||
nanoid,
|
||||
VIEW_TYPE_EXCALIDRAW,
|
||||
MAX_IMAGE_SIZE,
|
||||
COLOR_NAMES,
|
||||
fileid,
|
||||
@@ -55,14 +54,14 @@ import {
|
||||
wrapTextAtCharLength,
|
||||
arrayToMap,
|
||||
} from "src/utils/Utils";
|
||||
import { getAttachmentsFolderAndFilePath, getLeaf, getNewOrAdjacentLeaf, isObsidianThemeDark, mergeMarkdownFiles, openLeaf } from "src/utils/ObsidianUtils";
|
||||
import { AppState, BinaryFileData, DataURL, ExcalidrawImperativeAPI, Point } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
import { getAttachmentsFolderAndFilePath, getExcalidrawViews, getLeaf, getNewOrAdjacentLeaf, isObsidianThemeDark, mergeMarkdownFiles, openLeaf } from "src/utils/ObsidianUtils";
|
||||
import { AppState, BinaryFileData, DataURL, ExcalidrawImperativeAPI } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
import { EmbeddedFile, EmbeddedFilesLoader, FileData } from "src/EmbeddedFileLoader";
|
||||
import { tex2dataURL } from "src/LaTeX";
|
||||
import { GenericInputPrompt, NewFileActions } from "src/dialogs/Prompt";
|
||||
import { t } from "src/lang/helpers";
|
||||
import { ScriptEngine } from "src/Scripts";
|
||||
import { ConnectionPoint, DeviceType } from "src/types/types";
|
||||
import { ConnectionPoint, DeviceType, Point } from "src/types/types";
|
||||
import CM, { ColorMaster, extendPlugins } from "@zsviczian/colormaster";
|
||||
import HarmonyPlugin from "@zsviczian/colormaster/plugins/harmony";
|
||||
import MixPlugin from "@zsviczian/colormaster/plugins/mix"
|
||||
@@ -1826,33 +1825,23 @@ export class ExcalidrawAutomate {
|
||||
*/
|
||||
setView(view?: ExcalidrawView | "first" | "active"): ExcalidrawView {
|
||||
if(!view) {
|
||||
const v = app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
const v = this.plugin.app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
if (v instanceof ExcalidrawView) {
|
||||
this.targetView = v;
|
||||
}
|
||||
else {
|
||||
const leaves =
|
||||
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
if (!leaves || leaves.length == 0) {
|
||||
return;
|
||||
}
|
||||
this.targetView = leaves[0].view as ExcalidrawView;
|
||||
this.targetView = getExcalidrawViews(this.plugin.app)[0];
|
||||
}
|
||||
}
|
||||
if (view == "active") {
|
||||
const v = app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
const v = this.plugin.app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
if (!(v instanceof ExcalidrawView)) {
|
||||
return;
|
||||
}
|
||||
this.targetView = v;
|
||||
}
|
||||
if (view == "first") {
|
||||
const leaves =
|
||||
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
if (!leaves || leaves.length == 0) {
|
||||
return;
|
||||
}
|
||||
this.targetView = leaves[0].view as ExcalidrawView;
|
||||
this.targetView = getExcalidrawViews(this.plugin.app)[0];
|
||||
}
|
||||
if (view instanceof ExcalidrawView) {
|
||||
this.targetView = view;
|
||||
@@ -2989,8 +2978,12 @@ async function getTemplate(
|
||||
));
|
||||
}
|
||||
|
||||
const fileIDWhiteList = new Set<FileId>();
|
||||
groupElements.filter(el=>el.type==="image").forEach((el:ExcalidrawImageElement)=>fileIDWhiteList.add(el.fileId));
|
||||
let fileIDWhiteList:Set<FileId>;
|
||||
|
||||
if(groupElements.length < scene.elements.length) {
|
||||
fileIDWhiteList = new Set<FileId>();
|
||||
groupElements.filter(el=>el.type==="image").forEach((el:ExcalidrawImageElement)=>fileIDWhiteList.add(el.fileId));
|
||||
}
|
||||
|
||||
if (loadFiles) {
|
||||
//debug({where:"getTemplate",template:file.name,loader:loader.uid});
|
||||
@@ -3019,11 +3012,15 @@ async function getTemplate(
|
||||
let files:any = {};
|
||||
const sceneFilesSize = Object.values(scene.files).length;
|
||||
if (sceneFilesSize > 0) {
|
||||
if(sceneFilesSize === fileIDWhiteList.size)
|
||||
Object.values(scene.files).filter((f: any) => fileIDWhiteList.has(f.id)).forEach((f: any) => {
|
||||
files[f.id] = f;
|
||||
});
|
||||
if(fileIDWhiteList && (sceneFilesSize > fileIDWhiteList.size)) {
|
||||
Object.values(scene.files).filter((f: any) => fileIDWhiteList.has(f.id)).forEach((f: any) => {
|
||||
files[f.id] = f;
|
||||
});
|
||||
} else {
|
||||
files = scene.files;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
elements: convertMarkdownLinksToObsidianURLs
|
||||
? updateElementLinksToObsidianLinks({
|
||||
|
||||
@@ -2325,14 +2325,35 @@ export default class ExcalidrawView extends TextFileView {
|
||||
});
|
||||
}
|
||||
|
||||
private getGridColor(bgColor: string, st: AppState):{Bold: string, Regular: string} {
|
||||
private getGridColor(bgColor: string, st: AppState): { Bold: string, Regular: string } {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.getGridColor, "ExcalidrawView.getGridColor", bgColor, st);
|
||||
|
||||
const cm = this.plugin.ea.getCM(bgColor);
|
||||
const isDark = cm.isDark();
|
||||
const Regular = (isDark ? cm.lighterBy(7) : cm.darkerBy(7)).stringHEX({alpha: false});
|
||||
const Bold = (isDark ? cm.lighterBy(14) : cm.darkerBy(14)).stringHEX({alpha: false});
|
||||
return {Bold, Regular};
|
||||
|
||||
let Regular: string;
|
||||
let Bold: string;
|
||||
const opacity = this.plugin.settings.gridSettings.OPACITY/100;
|
||||
|
||||
if (this.plugin.settings.gridSettings.DYNAMIC_COLOR) {
|
||||
// Dynamic color: concatenate opacity to the HEX string
|
||||
Regular = (isDark ? cm.lighterBy(7) : cm.darkerBy(7)).alphaTo(opacity).stringRGB({ alpha: true });
|
||||
Bold = (isDark ? cm.lighterBy(14) : cm.darkerBy(14)).alphaTo(opacity).stringRGB({ alpha: true });
|
||||
} else {
|
||||
// Custom color handling
|
||||
const customCM = this.plugin.ea.getCM(this.plugin.settings.gridSettings.COLOR);
|
||||
const customIsDark = customCM.isDark();
|
||||
|
||||
// Regular uses the custom color directly
|
||||
Regular = customCM.alphaTo(opacity).stringRGB({ alpha: true });
|
||||
|
||||
// Bold is 7 shades lighter or darker based on the custom color's darkness
|
||||
Bold = (customIsDark ? customCM.lighterBy(7) : customCM.darkerBy(7)).alphaTo(opacity).stringRGB({ alpha: true });
|
||||
}
|
||||
|
||||
return { Bold, Regular };
|
||||
}
|
||||
|
||||
|
||||
public activeLoader: EmbeddedFilesLoader = null;
|
||||
private nextLoader: EmbeddedFilesLoader = null;
|
||||
@@ -3618,6 +3639,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
|
||||
private excalidrawDIVonKeyDown(event: KeyboardEvent) {
|
||||
//(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.excalidrawDIVonKeyDown, "ExcalidrawView.excalidrawDIVonKeyDown", event);
|
||||
if (this.semaphores?.viewunload) return;
|
||||
if (event.target === this.excalidrawWrapperRef.current) {
|
||||
return;
|
||||
} //event should originate from the canvas
|
||||
@@ -3744,10 +3766,18 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
}
|
||||
|
||||
public updateGridColor(canvasColor?: string, st?: any) {
|
||||
if(!canvasColor) {
|
||||
st = (this.excalidrawAPI as ExcalidrawImperativeAPI).getAppState();
|
||||
canvasColor = canvasColor ?? st.viewBackgroundColor === "transparent" ? "white" : st.viewBackgroundColor;
|
||||
}
|
||||
window.setTimeout(()=>this.updateScene({appState:{gridColor: this.getGridColor(canvasColor, st)}, storeAction: "update"}));
|
||||
}
|
||||
|
||||
private canvasColorChangeHook(st: AppState) {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(this.canvasColorChangeHook, "ExcalidrawView.canvasColorChangeHook", st);
|
||||
const canvasColor = st.viewBackgroundColor === "transparent" ? "white" : st.viewBackgroundColor;
|
||||
window.setTimeout(()=>this.updateScene({appState:{gridColor: this.getGridColor(canvasColor, st)}, storeAction: "update"}));
|
||||
this.updateGridColor(canvasColor,st);
|
||||
setDynamicStyle(this.plugin.ea,this,canvasColor,this.plugin.settings.dynamicStyling);
|
||||
if(this.plugin.ea.onCanvasColorChangeHook) {
|
||||
try {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
TFile,
|
||||
WorkspaceLeaf,
|
||||
} from "obsidian";
|
||||
import { PLUGIN_ID, VIEW_TYPE_EXCALIDRAW } from "./constants/constants";
|
||||
import { PLUGIN_ID } from "./constants/constants";
|
||||
import ExcalidrawView from "./ExcalidrawView";
|
||||
import ExcalidrawPlugin from "./main";
|
||||
import { ButtonDefinition, GenericInputPrompt, GenericSuggester } from "./dialogs/Prompt";
|
||||
@@ -14,6 +14,7 @@ import { splitFolderAndFilename } from "./utils/FileUtils";
|
||||
import { getEA } from "src";
|
||||
import { ExcalidrawAutomate } from "./ExcalidrawAutomate";
|
||||
import { WeakArray } from "./utils/WeakArray";
|
||||
import { getExcalidrawViews } from "./utils/ObsidianUtils";
|
||||
|
||||
export type ScriptIconMap = {
|
||||
[key: string]: { name: string; group: string; svgString: string };
|
||||
@@ -303,10 +304,8 @@ export class ScriptEngine {
|
||||
}
|
||||
|
||||
private updateToolPannels() {
|
||||
const leaves =
|
||||
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
leaves.forEach((leaf: WorkspaceLeaf) => {
|
||||
const excalidrawView = leaf.view as ExcalidrawView;
|
||||
const excalidrawViews = getExcalidrawViews(this.plugin.app);
|
||||
excalidrawViews.forEach(excalidrawView => {
|
||||
excalidrawView.toolsPanelRef?.current?.updateScriptIconMap(
|
||||
this.scriptIconMap,
|
||||
);
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { ExcalidrawImperativeAPI } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
import { ColorComponent, Modal, Setting, SliderComponent, TextComponent, ToggleComponent } from "obsidian";
|
||||
import { COLOR_NAMES, VIEW_TYPE_EXCALIDRAW } from "src/constants/constants";
|
||||
import { ColorComponent, Modal, Setting, TextComponent, ToggleComponent } from "obsidian";
|
||||
import { COLOR_NAMES } from "src/constants/constants";
|
||||
import ExcalidrawView from "src/ExcalidrawView";
|
||||
import ExcalidrawPlugin from "src/main";
|
||||
import { setPen } from "src/menu/ObsidianMenu";
|
||||
import { ExtendedFillStyle, PenStyle, PenType } from "src/PenTypes";
|
||||
import { ExtendedFillStyle, PenType } from "src/PenTypes";
|
||||
import { getExcalidrawViews } from "src/utils/ObsidianUtils";
|
||||
import { PENS } from "src/utils/Pens";
|
||||
import { fragWithHTML, getExportPadding, getExportTheme, getPNGScale, getWithBackground } from "src/utils/Utils";
|
||||
import { fragWithHTML } from "src/utils/Utils";
|
||||
import { __values } from "tslib";
|
||||
|
||||
const EASINGFUNCTIONS: Record<string,string> = {
|
||||
@@ -65,9 +66,7 @@ export class PenSettingsModal extends Modal {
|
||||
|
||||
async onClose() {
|
||||
if(this.dirty) {
|
||||
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
|
||||
if (v.view instanceof ExcalidrawView) v.view.updatePinnedCustomPens()
|
||||
})
|
||||
getExcalidrawViews(this.app).forEach(excalidrawView=>excalidrawView.updatePinnedCustomPens());
|
||||
this.plugin.saveSettings();
|
||||
const pen = this.plugin.settings.customPens[this.pen]
|
||||
const api = this.view.excalidrawAPI;
|
||||
|
||||
@@ -3,7 +3,7 @@ import "obsidian";
|
||||
//export ExcalidrawAutomate from "./ExcalidrawAutomate";
|
||||
//export {ExcalidrawAutomate} from "./ExcaildrawAutomate";
|
||||
export type { ExcalidrawBindableElement, ExcalidrawElement, FileId, FillStyle, StrokeRoundness, StrokeStyle } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
export type { Point } from "@zsviczian/excalidraw/types/excalidraw/types";
|
||||
export type { Point } from "src/types/types";
|
||||
export const getEA = (view?:any): any => {
|
||||
try {
|
||||
return window.ExcalidrawAutomate.getAPI(view);
|
||||
|
||||
@@ -395,6 +395,14 @@ FILENAME_HEAD: "Filename",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_NAME: "Zoom to fit max ZOOM level",
|
||||
ZOOM_TO_FIT_MAX_LEVEL_DESC:
|
||||
"Set the maximum level to which zoom to fit will enlarge the drawing. Minimum is 0.5 (50%) and maximum is 10 (1000%).",
|
||||
GRID_HEAD: "Grid",
|
||||
GRID_DYNAMIC_COLOR_NAME: "Dynamic grid color",
|
||||
GRID_DYNAMIC_COLOR_DESC:
|
||||
"<b><u>Toggle ON:</u></b>Change grid color to match the canvas color<br><b><u>Toggle OFF:</u></b>Use the color below as the grid color",
|
||||
GRID_COLOR_NAME: "Grid color",
|
||||
GRID_OPACITY_NAME: "Grid opacity",
|
||||
GRID_OPACITY_DESC: "Grid opacity will also control the opacity of the binding box when binding an arrow to an element.<br>" +
|
||||
"Set the opacity of the grid. 0 is transparent, 1 is opaque.",
|
||||
LASER_HEAD: "Laser pointer",
|
||||
LASER_COLOR: "Laser pointer color",
|
||||
LASER_DECAY_TIME_NAME: "Laser pointer decay time",
|
||||
|
||||
28
src/main.ts
28
src/main.ts
@@ -101,7 +101,7 @@ import {
|
||||
versionUpdateCheckTimer,
|
||||
getFontMetrics,
|
||||
} from "./utils/Utils";
|
||||
import { editorInsertText, extractSVGPNGFileName, foldExcalidrawSection, getActivePDFPageNumberFromPDFView, getAttachmentsFolderAndFilePath, getNewOrAdjacentLeaf, getParentOfClass, isObsidianThemeDark, mergeMarkdownFiles, openLeaf, setExcalidrawView } from "./utils/ObsidianUtils";
|
||||
import { editorInsertText, extractSVGPNGFileName, foldExcalidrawSection, getActivePDFPageNumberFromPDFView, getAttachmentsFolderAndFilePath, getExcalidrawViews, getNewOrAdjacentLeaf, getParentOfClass, isObsidianThemeDark, mergeMarkdownFiles, openLeaf, setExcalidrawView } from "./utils/ObsidianUtils";
|
||||
import { ExcalidrawElement, ExcalidrawEmbeddableElement, ExcalidrawImageElement, ExcalidrawTextElement, FileId } from "@zsviczian/excalidraw/types/excalidraw/element/types";
|
||||
import { ScriptEngine } from "./Scripts";
|
||||
import {
|
||||
@@ -758,9 +758,8 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
setTimeout(()=>{ //run async to avoid blocking the UI
|
||||
const theme = isObsidianThemeDark() ? "dark" : "light";
|
||||
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
leaves.forEach((leaf: WorkspaceLeaf) => {
|
||||
const excalidrawView = leaf.view as ExcalidrawView;
|
||||
const excalidrawViews = getExcalidrawViews(this.app);
|
||||
excalidrawViews.forEach(excalidrawView => {
|
||||
if (excalidrawView.file && excalidrawView.excalidrawAPI) {
|
||||
excalidrawView.setTheme(theme);
|
||||
}
|
||||
@@ -1495,7 +1494,6 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
this.addCommand({
|
||||
id: "toggle-lock",
|
||||
hotkeys: [{ modifiers: ["Ctrl" || "Meta", "Shift"], key: "e" }],
|
||||
name: t("TOGGLE_LOCK"),
|
||||
checkCallback: (checking: boolean) => {
|
||||
if (checking) {
|
||||
@@ -1585,7 +1583,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
this.addCommand({
|
||||
id: "insert-link",
|
||||
hotkeys: [{ modifiers: ["Ctrl" || "Meta", "Shift"], key: "k" }],
|
||||
hotkeys: [{ modifiers: ["Mod", "Shift"], key: "k" }],
|
||||
name: t("INSERT_LINK"),
|
||||
checkCallback: (checking: boolean) => {
|
||||
if (checking) {
|
||||
@@ -1618,7 +1616,6 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
this.addCommand({
|
||||
id: "insert-link-to-element",
|
||||
hotkeys: [{ modifiers: ["Ctrl" || "Meta", "Shift"], key: "k" }],
|
||||
name: t("INSERT_LINK_TO_ELEMENT_NORMAL"),
|
||||
checkCallback: (checking: boolean) => {
|
||||
if (checking) {
|
||||
@@ -2951,9 +2948,8 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
|
||||
const modifyEventHandler = async (file: TFile) => {
|
||||
(process.env.NODE_ENV === 'development') && DEBUGGING && debug(modifyEventHandler,`ExcalidrawPlugin.modifyEventHandler`, file);
|
||||
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
leaves.forEach(async (leaf: WorkspaceLeaf) => {
|
||||
const excalidrawView = leaf.view as ExcalidrawView;
|
||||
const excalidrawViews = getExcalidrawViews(this.app);
|
||||
excalidrawViews.forEach(async (excalidrawView) => {
|
||||
if(excalidrawView.semaphores?.viewunload) {
|
||||
return;
|
||||
}
|
||||
@@ -3013,10 +3009,10 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
|
||||
//close excalidraw view where this file is open
|
||||
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
for (let i = 0; i < leaves.length; i++) {
|
||||
if ((leaves[i].view as ExcalidrawView).file.path == file.path) {
|
||||
await leaves[i].setViewState({
|
||||
const excalidrawViews = getExcalidrawViews(this.app);
|
||||
for (const excalidrawView of excalidrawViews) {
|
||||
if (excalidrawView.file.path === file.path) {
|
||||
await excalidrawView.leaf.setViewState({
|
||||
type: VIEW_TYPE_EXCALIDRAW,
|
||||
state: { file: null },
|
||||
});
|
||||
@@ -3212,8 +3208,8 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
}
|
||||
|
||||
onunload() {
|
||||
const excalidrawLeaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
excalidrawLeaves.forEach((leaf) => {
|
||||
const excalidrawViews = getExcalidrawViews(this.app);
|
||||
excalidrawViews.forEach(({leaf}) => {
|
||||
this.setMarkdownView(leaf);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { AppState, ExcalidrawImperativeAPI } from "@zsviczian/excalidraw/types/e
|
||||
import clsx from "clsx";
|
||||
import { TFile } from "obsidian";
|
||||
import * as React from "react";
|
||||
import { DEVICE, VIEW_TYPE_EXCALIDRAW } from "src/constants/constants";
|
||||
import { DEVICE } from "src/constants/constants";
|
||||
import { PenSettingsModal } from "src/dialogs/PenSettingsModal";
|
||||
import ExcalidrawView from "src/ExcalidrawView";
|
||||
import { PenStyle } from "src/PenTypes";
|
||||
@@ -11,8 +11,7 @@ import ExcalidrawPlugin from "../main";
|
||||
import { ICONS, penIcon, stringToSVG } from "./ActionIcons";
|
||||
import { UniversalInsertFileModal } from "src/dialogs/UniversalInsertFileModal";
|
||||
import { t } from "src/lang/helpers";
|
||||
|
||||
declare const PLUGIN_VERSION:string;
|
||||
import { getExcalidrawViews } from "src/utils/ObsidianUtils";
|
||||
|
||||
export function setPen (pen: PenStyle, api: any) {
|
||||
const st = api.getAppState();
|
||||
@@ -134,10 +133,8 @@ export class ObsidianMenu {
|
||||
this.view.excalidrawAPI?.setToast({message:`Pin removed: ${name}`, duration: 3000, closable: true});
|
||||
}
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
|
||||
if (v.view instanceof ExcalidrawView) v.view.updatePinnedScripts()
|
||||
})
|
||||
})()
|
||||
getExcalidrawViews(this.plugin.app).forEach(excalidrawView=>excalidrawView.updatePinnedScripts());
|
||||
})()
|
||||
},
|
||||
1500
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Notice, TFile } from "obsidian";
|
||||
import * as React from "react";
|
||||
import { ActionButton } from "./ActionButton";
|
||||
import { ICONS, saveIcon, stringToSVG } from "./ActionIcons";
|
||||
import { DEVICE, SCRIPT_INSTALL_FOLDER, VIEW_TYPE_EXCALIDRAW } from "../constants/constants";
|
||||
import { DEVICE, SCRIPT_INSTALL_FOLDER } from "../constants/constants";
|
||||
import { insertLaTeXToView, search } from "../ExcalidrawAutomate";
|
||||
import ExcalidrawView, { TextMode } from "../ExcalidrawView";
|
||||
import { t } from "../lang/helpers";
|
||||
@@ -18,10 +18,9 @@ import { openExternalLink } from "src/utils/ExcalidrawViewUtils";
|
||||
import { UniversalInsertFileModal } from "src/dialogs/UniversalInsertFileModal";
|
||||
import { DEBUGGING, debug } from "src/utils/DebugHelper";
|
||||
import { REM_VALUE } from "src/utils/StylesManager";
|
||||
import { getExcalidrawViews } from "src/utils/ObsidianUtils";
|
||||
|
||||
declare const PLUGIN_VERSION:string;
|
||||
const dark = '<svg style="stroke:#ced4da;#212529;color:#ced4da;fill:#ced4da" ';
|
||||
const light = '<svg style="stroke:#212529;color:#212529;fill:#212529" ';
|
||||
|
||||
type PanelProps = {
|
||||
visible: boolean;
|
||||
@@ -43,7 +42,7 @@ export type PanelState = {
|
||||
scriptIconMap: ScriptIconMap | null;
|
||||
};
|
||||
|
||||
const TOOLS_PANEL_WIDTH = () => REM_VALUE * 14.2;
|
||||
const TOOLS_PANEL_WIDTH = () => REM_VALUE * 14.4;
|
||||
|
||||
export class ToolsPanel extends React.Component<PanelProps, PanelState> {
|
||||
pos1: number = 0;
|
||||
@@ -367,11 +366,11 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
|
||||
async actionRunScript(key: string) {
|
||||
const view = this.view;
|
||||
const plugin = view.plugin;
|
||||
const f = app.vault.getAbstractFileByPath(key);
|
||||
const f = plugin.app.vault.getAbstractFileByPath(key);
|
||||
if (f && f instanceof TFile) {
|
||||
plugin.scriptEngine.executeScript(
|
||||
view,
|
||||
await app.vault.read(f),
|
||||
await plugin.app.vault.read(f),
|
||||
plugin.scriptEngine.getScriptName(f),
|
||||
f
|
||||
);
|
||||
@@ -392,9 +391,7 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
|
||||
api?.setToast({message:`Pinned: ${scriptName}`, duration: 3000, closable: true})
|
||||
}
|
||||
await plugin.saveSettings();
|
||||
plugin.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
|
||||
if (v.view instanceof ExcalidrawView) v.view.updatePinnedScripts()
|
||||
})
|
||||
getExcalidrawViews(plugin.app).forEach(excalidrawView=>excalidrawView.updatePinnedScripts());
|
||||
}
|
||||
|
||||
private islandOnClick(event: React.MouseEvent<HTMLDivElement, MouseEvent>) {
|
||||
@@ -454,7 +451,7 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
|
||||
style={{
|
||||
top: `${this.state.top}px`,
|
||||
left: `${this.state.left}px`,
|
||||
width: `13.75rem`,
|
||||
width: `14.4rem`,
|
||||
display:
|
||||
this.state.visible && !this.state.excalidrawViewMode
|
||||
? "block"
|
||||
@@ -493,7 +490,7 @@ export class ToolsPanel extends React.Component<PanelProps, PanelState> {
|
||||
maxHeight: "350px",
|
||||
width: "initial",
|
||||
//@ts-ignore
|
||||
"--padding": 2,
|
||||
"--padding": "0.125rem",
|
||||
display: this.state.minimized ? "none" : "block",
|
||||
}}
|
||||
>
|
||||
|
||||
122
src/settings.ts
122
src/settings.ts
@@ -10,12 +10,11 @@ import {
|
||||
TextComponent,
|
||||
TFile,
|
||||
} from "obsidian";
|
||||
import { GITHUB_RELEASES, VIEW_TYPE_EXCALIDRAW } from "./constants/constants";
|
||||
import ExcalidrawView from "./ExcalidrawView";
|
||||
import { GITHUB_RELEASES } from "./constants/constants";
|
||||
import { t } from "./lang/helpers";
|
||||
import type ExcalidrawPlugin from "./main";
|
||||
import { PenStyle } from "./PenTypes";
|
||||
import { DynamicStyle } from "./types/types";
|
||||
import { DynamicStyle, GridSettings } from "./types/types";
|
||||
import { PreviewImageType } from "./utils/UtilTypes";
|
||||
import { setDynamicStyle } from "./utils/DynamicStyling";
|
||||
import {
|
||||
@@ -41,6 +40,7 @@ import { setDebugging } from "./utils/DebugHelper";
|
||||
import { Rank } from "./menu/ActionIcons";
|
||||
import { TAG_AUTOEXPORT, TAG_MDREADINGMODE, TAG_PDFEXPORT } from "src/constants/constSettingsTags";
|
||||
import { HotkeyEditor } from "./dialogs/HotkeyEditor";
|
||||
import { getExcalidrawViews } from "./utils/ObsidianUtils";
|
||||
|
||||
export interface ExcalidrawSettings {
|
||||
folder: string;
|
||||
@@ -179,6 +179,7 @@ export interface ExcalidrawSettings {
|
||||
pdfNumRows: number;
|
||||
pdfDirection: "down" | "right";
|
||||
pdfImportScale: number;
|
||||
gridSettings: GridSettings;
|
||||
laserSettings: {
|
||||
DECAY_TIME: number,
|
||||
DECAY_LENGTH: number,
|
||||
@@ -355,6 +356,11 @@ export const DEFAULT_SETTINGS: ExcalidrawSettings = {
|
||||
pdfNumRows: 1,
|
||||
pdfDirection: "right",
|
||||
pdfImportScale: 0.3,
|
||||
gridSettings: {
|
||||
DYNAMIC_COLOR: true,
|
||||
COLOR: "#000000",
|
||||
OPACITY: 50,
|
||||
},
|
||||
laserSettings: {
|
||||
DECAY_LENGTH: 50,
|
||||
DECAY_TIME: 1000,
|
||||
@@ -509,31 +515,25 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
}
|
||||
this.plugin.saveSettings();
|
||||
if (this.requestUpdatePinnedPens) {
|
||||
this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
|
||||
if (v.view instanceof ExcalidrawView) v.view.updatePinnedCustomPens()
|
||||
})
|
||||
getExcalidrawViews(this.app).forEach(excalidrawView =>
|
||||
excalidrawView.updatePinnedCustomPens()
|
||||
)
|
||||
}
|
||||
if (this.requestUpdateDynamicStyling) {
|
||||
this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
|
||||
if (v.view instanceof ExcalidrawView) {
|
||||
setDynamicStyle(this.plugin.ea,v.view,v.view.previousBackgroundColor,this.plugin.settings.dynamicStyling);
|
||||
}
|
||||
|
||||
})
|
||||
getExcalidrawViews(this.app).forEach(excalidrawView =>
|
||||
setDynamicStyle(this.plugin.ea,excalidrawView,excalidrawView.previousBackgroundColor,this.plugin.settings.dynamicStyling)
|
||||
)
|
||||
}
|
||||
this.hotkeyEditor.unload();
|
||||
if (this.hotkeyEditor.isDirty) {
|
||||
this.plugin.registerHotkeyOverrides();
|
||||
}
|
||||
if (this.requestReloadDrawings) {
|
||||
const exs =
|
||||
this.app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW);
|
||||
for (const v of exs) {
|
||||
if (v.view instanceof ExcalidrawView) {
|
||||
await v.view.save(false);
|
||||
//debug({where:"ExcalidrawSettings.hide",file:v.view.file.name,before:"reload(true)"})
|
||||
await v.view.reload(true);
|
||||
}
|
||||
const excalidrawViews = getExcalidrawViews(this.app);
|
||||
for (const excalidrawView of excalidrawViews) {
|
||||
await excalidrawView.save(false);
|
||||
//debug({where:"ExcalidrawSettings.hide",file:v.view.file.name,before:"reload(true)"})
|
||||
await excalidrawView.reload(true);
|
||||
}
|
||||
this.requestEmbedUpdate = true;
|
||||
}
|
||||
@@ -1241,9 +1241,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
.setValue(this.plugin.settings.allowPinchZoom)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.allowPinchZoom = value;
|
||||
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
|
||||
if (v.view instanceof ExcalidrawView) v.view.updatePinchZoom()
|
||||
})
|
||||
getExcalidrawViews(this.app).forEach(excalidrawView=>excalidrawView.updatePinchZoom())
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
@@ -1257,9 +1255,7 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
.setValue(this.plugin.settings.allowWheelZoom)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.allowWheelZoom = value;
|
||||
app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).forEach(v=> {
|
||||
if (v.view instanceof ExcalidrawView) v.view.updateWheelZoom()
|
||||
})
|
||||
getExcalidrawViews(this.app).forEach(excalidrawView=>excalidrawView.updateWheelZoom());
|
||||
this.applySettingsUpdate();
|
||||
}),
|
||||
);
|
||||
@@ -1310,7 +1306,79 @@ export class ExcalidrawSettingTab extends PluginSettingTab {
|
||||
el.innerText = ` ${this.plugin.settings.zoomToFitMaxLevel.toString()}`;
|
||||
});
|
||||
|
||||
|
||||
// ------------------------------------------------
|
||||
// Grid
|
||||
// ------------------------------------------------
|
||||
detailsEl = displayDetailsEl.createEl("details");
|
||||
detailsEl.createEl("summary", {
|
||||
text: t("GRID_HEAD"),
|
||||
cls: "excalidraw-setting-h3",
|
||||
});
|
||||
|
||||
const updateGridColor = () => {
|
||||
getExcalidrawViews(this.app).forEach(excalidrawView=>excalidrawView.updateGridColor());
|
||||
};
|
||||
|
||||
// Dynamic color toggle
|
||||
let gridColorSection: HTMLDivElement;
|
||||
new Setting(detailsEl)
|
||||
.setName(t("GRID_DYNAMIC_COLOR_NAME"))
|
||||
.setDesc(fragWithHTML(t("GRID_DYNAMIC_COLOR_DESC")))
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(this.plugin.settings.gridSettings.DYNAMIC_COLOR)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.gridSettings.DYNAMIC_COLOR = value;
|
||||
gridColorSection.style.display = value ? "none" : "block";
|
||||
this.applySettingsUpdate();
|
||||
updateGridColor();
|
||||
}),
|
||||
);
|
||||
|
||||
// Create a div to contain color and opacity settings
|
||||
gridColorSection = detailsEl.createDiv();
|
||||
gridColorSection.style.display = this.plugin.settings.gridSettings.DYNAMIC_COLOR ? "none" : "block";
|
||||
|
||||
// Grid color picker
|
||||
new Setting(gridColorSection)
|
||||
.setName(t("GRID_COLOR_NAME"))
|
||||
.addColorPicker((colorPicker) =>
|
||||
colorPicker
|
||||
.setValue(this.plugin.settings.gridSettings.COLOR)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.gridSettings.COLOR = value;
|
||||
this.applySettingsUpdate();
|
||||
updateGridColor();
|
||||
}),
|
||||
);
|
||||
|
||||
// Grid opacity slider (hex value between 00 and FF)
|
||||
let opacityValue: HTMLDivElement;
|
||||
new Setting(detailsEl)
|
||||
.setName(t("GRID_OPACITY_NAME"))
|
||||
.setDesc(fragWithHTML(t("GRID_OPACITY_DESC")))
|
||||
.addSlider((slider) =>
|
||||
slider
|
||||
.setLimits(0, 100, 1) // 0 to 100 in decimal
|
||||
.setValue(this.plugin.settings.gridSettings.OPACITY)
|
||||
.onChange(async (value) => {
|
||||
opacityValue.innerText = ` ${value.toString()}`;
|
||||
this.plugin.settings.gridSettings.OPACITY = value;
|
||||
this.applySettingsUpdate();
|
||||
updateGridColor();
|
||||
}),
|
||||
)
|
||||
.settingEl.createDiv("", (el) => {
|
||||
opacityValue = el;
|
||||
el.style.minWidth = "3em";
|
||||
el.style.textAlign = "right";
|
||||
el.innerText = ` ${this.plugin.settings.gridSettings.OPACITY}`;
|
||||
});
|
||||
|
||||
|
||||
// ------------------------------------------------
|
||||
// Laser Pointer
|
||||
// ------------------------------------------------
|
||||
detailsEl = displayDetailsEl.createEl("details");
|
||||
detailsEl.createEl("summary", {
|
||||
text: t("LASER_HEAD"),
|
||||
|
||||
8
src/types/types.d.ts
vendored
8
src/types/types.d.ts
vendored
@@ -13,6 +13,12 @@ export type ValueOf<T> = T[keyof T];
|
||||
|
||||
export type DynamicStyle = "none" | "gray" | "colorful";
|
||||
|
||||
export type GridSettings = {
|
||||
DYNAMIC_COLOR: boolean; // Whether the grid color is dynamic
|
||||
COLOR: string; // The grid color (in hex format)
|
||||
OPACITY: number; // The grid opacity (hex value between "00" and "FF")
|
||||
};
|
||||
|
||||
export type DeviceType = {
|
||||
isDesktop: boolean,
|
||||
isPhone: boolean,
|
||||
@@ -25,6 +31,8 @@ export type DeviceType = {
|
||||
isAndroid: boolean,
|
||||
};
|
||||
|
||||
export type Point = [number, number];
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
ExcalidrawAutomate: ExcalidrawAutomate;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { getEA } from "src";
|
||||
import { ExcalidrawAutomate } from "src/ExcalidrawAutomate";
|
||||
import { getCropFileNameAndFolder, getListOfTemplateFiles, splitFolderAndFilename } from "./FileUtils";
|
||||
import { Notice, TFile } from "obsidian";
|
||||
import { Radians } from "@zsviczian/excalidraw/types/math";
|
||||
|
||||
export const CROPPED_PREFIX = "cropped_";
|
||||
export const ANNOTATED_PREFIX = "annotated_";
|
||||
@@ -30,7 +31,7 @@ export const carveOutImage = async (sourceEA: ExcalidrawAutomate, viewImageEl: E
|
||||
const scale = newImage.scale;
|
||||
const angle = newImage.angle;
|
||||
newImage.scale = [1,1];
|
||||
newImage.angle = 0;
|
||||
newImage.angle = 0 as Radians;
|
||||
|
||||
const ef = sourceEA.targetView.excalidrawData.getFile(viewImageEl.fileId);
|
||||
let imageLink = "";
|
||||
|
||||
@@ -82,6 +82,7 @@ export const setDynamicStyle = (
|
||||
[`--color-surface-high`]: str(gray1().lighterBy(step)),
|
||||
[`--color-on-primary-container`]: str(!isDark?accent().darkerBy(15):accent().lighterBy(15)),
|
||||
[`--color-surface-primary-container`]: str(isDark?accent().darkerBy(step):accent().lighterBy(step)),
|
||||
[`--bold-color`]: str(!isDark?accent().darkerBy(15):accent().lighterBy(15)),
|
||||
//[`--color-primary-darker`]: str(accent().darkerBy(step)),
|
||||
//[`--color-primary-darkest`]: str(accent().darkerBy(step)),
|
||||
[`--button-gray-1`]: str(gray1()),
|
||||
@@ -96,6 +97,7 @@ export const setDynamicStyle = (
|
||||
[`--overlay-bg-color`]: gray2().alphaTo(0.6).stringHEX(),
|
||||
[`--popup-bg-color`]: str(gray1()),
|
||||
[`--color-on-surface`]: str(text),
|
||||
[`--default-border-color`]: str(text),
|
||||
//[`--color-gray-100`]: str(text),
|
||||
[`--color-gray-40`]: str(text), //frame
|
||||
[`--color-gray-50`]: str(text), //frame
|
||||
@@ -117,6 +119,8 @@ export const setDynamicStyle = (
|
||||
['--excalidraw-caret-color']: str(isLightTheme ? text : cmBG()),
|
||||
[`--select-highlight-color`]: str(gray1()),
|
||||
[`--color-gray-80`]: str(isDark?text.darkerBy(40):text.lighterBy(40)), //frame
|
||||
[`--color-gray-90`]: str(isDark?text.darkerBy(5):text.lighterBy(5)), //search background
|
||||
[`--default-bg-color`]: str(text), //search background,
|
||||
};
|
||||
|
||||
const styleString = Object.keys(styleObject)
|
||||
|
||||
@@ -129,8 +129,9 @@ export function openExternalLink (link:string, app: App, element?: ExcalidrawEle
|
||||
* the link to the file path. By default as a wiki link, or as a file path if returnWikiLink is false.
|
||||
*/
|
||||
export function parseObsidianLink(link: string, app: App, returnWikiLink: boolean = true): boolean | string {
|
||||
if(!link) return false;
|
||||
link = getLinkFromMarkdownLink(link);
|
||||
if (!link.startsWith("obsidian://")) {
|
||||
if (!link?.startsWith("obsidian://")) {
|
||||
return false;
|
||||
}
|
||||
const url = new URL(link);
|
||||
@@ -394,4 +395,4 @@ export function isTextImageTransclusion (
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ import ExcalidrawPlugin from "../main";
|
||||
import { checkAndCreateFolder, splitFolderAndFilename } from "./FileUtils";
|
||||
import { linkClickModifierType, ModifierKeys } from "./ModifierkeyHelper";
|
||||
import { REG_BLOCK_REF_CLEAN, REG_SECTION_REF_CLEAN, VIEW_TYPE_EXCALIDRAW } from "src/constants/constants";
|
||||
import yaml, { Mark } from "js-yaml";
|
||||
import yaml from "js-yaml";
|
||||
import { debug, DEBUGGING } from "./DebugHelper";
|
||||
import ExcalidrawView from "src/ExcalidrawView";
|
||||
|
||||
export const getParentOfClass = (element: Element, cssClass: string):HTMLElement | null => {
|
||||
let parent = element.parentElement;
|
||||
@@ -24,6 +25,11 @@ export const getParentOfClass = (element: Element, cssClass: string):HTMLElement
|
||||
return parent?.classList?.contains(cssClass) ? parent : null;
|
||||
};
|
||||
|
||||
export function getExcalidrawViews(app: App): ExcalidrawView[] {
|
||||
const leaves = app.workspace.getLeavesOfType(VIEW_TYPE_EXCALIDRAW).filter(l=>l instanceof ExcalidrawView);
|
||||
return leaves.map(l=>l.view as ExcalidrawView);
|
||||
}
|
||||
|
||||
export const getLeaf = (
|
||||
plugin: ExcalidrawPlugin,
|
||||
origo: WorkspaceLeaf,
|
||||
|
||||
@@ -634,4 +634,8 @@ textarea.excalidraw-wysiwyg, .excalidraw input {
|
||||
|
||||
.excalidraw .color-picker-content input[type="color"] {
|
||||
filter: var(--theme-filter);
|
||||
}
|
||||
|
||||
.ExcTextField__input input::placeholder {
|
||||
color: var(--select-highlight-color);
|
||||
}
|
||||
Reference in New Issue
Block a user