mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
1.9.11
This commit is contained in:
@@ -50,8 +50,10 @@ const startFullscreen = !altKey;
|
||||
//For this reason event handlers are distributed between window and owner window depending on their role
|
||||
const ownerWindow = ea.targetView.ownerWindow;
|
||||
const excalidrawAPI = ea.getExcalidrawAPI();
|
||||
const frameRenderingOriginalState = excalidrawAPI.getAppState().frameRendering;
|
||||
const contentEl = ea.targetView.contentEl;
|
||||
const sleep = async (ms) => new Promise((resolve) => ownerWindow.setTimeout(resolve, ms));
|
||||
const getFrameName = (name, index) => name ?? `Frame ${(index+1).toString().padStart(2, '0')}`;
|
||||
|
||||
//-------------------------------
|
||||
//clean up potential clutter from previous run
|
||||
@@ -63,9 +65,10 @@ let presentationPathLineEl = ea.getViewElements()
|
||||
.filter(el=>["line","arrow"].contains(el.type) && el.customData?.slideshow)[0];
|
||||
let frames = ea.getViewElements()
|
||||
.filter(el=>el.type==="frame")
|
||||
.map((f,i)=>[f,i]) //because frame.name is null until set
|
||||
.sort((el1,el2)=>((el1[0].name??`Frame ${el1[1]}`)>(el2[0].name??`Frame ${el2[1]}`))?1:-1)
|
||||
.map((frame,index)=>[frame,index]) //because frame.name is null until set
|
||||
.sort((el1,el2)=> getFrameName(el1[0], el1[1]) > getFrameName(el2[0], el2[1]) ? -1:1)
|
||||
.map(el=>el[0]);
|
||||
|
||||
let presentationPathType = "line"; // "frame"
|
||||
const selectedEl = ea.getViewSelectedElement();
|
||||
let shouldHideArrowAfterPresentation = true; //this controls if the hide arrow button is available in settings
|
||||
@@ -124,7 +127,16 @@ if(presentationPathType === "frame") {
|
||||
y2: frame.y + frame.height
|
||||
});
|
||||
}
|
||||
excalidrawAPI.updateScene({appState:{shouldRenderFrames:false}});
|
||||
if(frameRenderingOriginalState.enabled) {
|
||||
excalidrawAPI.updateScene({
|
||||
appState: {
|
||||
frameRendering: {
|
||||
...frameRenderingOriginalState,
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
@@ -406,7 +418,9 @@ const createPresentationNavigationPanel = () => {
|
||||
}, selectEl => {
|
||||
for (let i = 0; i < slides.length; i++) {
|
||||
const option = document.createElement("option");
|
||||
option.text = `Slide ${i + 1}/${slides.length}`;
|
||||
option.text = (presentationPathType === "frame")
|
||||
? `${getFrameName(frames[i]?.name,i)}/${slides.length}`
|
||||
: option.text = `Slide ${i + 1}/${slides.length}`;
|
||||
option.value = i + 1;
|
||||
selectEl.add(option);
|
||||
}
|
||||
@@ -647,7 +661,16 @@ const exitPresentation = async (openForEdit = false) => {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
excalidrawAPI.updateScene({appState:{shouldRenderFrames:true}});
|
||||
if(frameRenderingOriginalState.enabled) {
|
||||
excalidrawAPI.updateScene({
|
||||
appState: {
|
||||
frameRendering: {
|
||||
...frameRenderingOriginalState,
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
window.removePresentationEventHandlers?.();
|
||||
ownerWindow.setTimeout(()=>{
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-excalidraw-plugin",
|
||||
"name": "Excalidraw",
|
||||
"version": "1.9.10",
|
||||
"version": "1.9.11",
|
||||
"minAppVersion": "1.1.6",
|
||||
"description": "An Obsidian plugin to edit and view Excalidraw drawings",
|
||||
"author": "Zsolt Viczian",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/lz-string": "^1.3.34",
|
||||
"@zsviczian/excalidraw": "0.15.2-obsidian-9",
|
||||
"@zsviczian/excalidraw": "0.15.2-obsidian-10",
|
||||
"chroma-js": "^2.4.2",
|
||||
"clsx": "^1.2.1",
|
||||
"colormaster": "^1.2.1",
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
intersectElementWithLine,
|
||||
measureText,
|
||||
DEVICE,
|
||||
restore,
|
||||
} from "src/Constants";
|
||||
import { getDrawingFilename, getNewUniqueFilepath, } from "src/utils/FileUtils";
|
||||
import {
|
||||
@@ -2607,7 +2608,7 @@ export function repositionElementsToCursor(
|
||||
element.y = element.y + offsetY;
|
||||
});
|
||||
|
||||
return api.restore({elements}).elements;
|
||||
return restore({elements}, null, null).elements;
|
||||
}
|
||||
|
||||
function errorMessage(message: string, source: string) {
|
||||
|
||||
@@ -719,7 +719,7 @@ export class ExcalidrawData {
|
||||
wrapAt ? wrapText(
|
||||
originalText,
|
||||
getFontString({fontSize: te.fontSize, fontFamily: te.fontFamily}),
|
||||
getBoundTextMaxWidth(container)
|
||||
getBoundTextMaxWidth(container as any)
|
||||
) : originalText,
|
||||
originalText,
|
||||
forceupdate,
|
||||
|
||||
116
src/ExcalidrawLib.d.ts
vendored
Normal file
116
src/ExcalidrawLib.d.ts
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
import { RestoredDataState } from "@zsviczian/excalidraw/types/data/restore";
|
||||
import { ImportedDataState } from "@zsviczian/excalidraw/types/data/types";
|
||||
import { BoundingBox } from "@zsviczian/excalidraw/types/element/bounds";
|
||||
import { ExcalidrawBindableElement, ExcalidrawElement, ExcalidrawTextElement, FontFamilyValues, FontString, NonDeleted } from "@zsviczian/excalidraw/types/element/types";
|
||||
import { AppState, BinaryFiles, ExportOpts, Point, Zoom } from "@zsviczian/excalidraw/types/types";
|
||||
import { Mutable } from "@zsviczian/excalidraw/types/utility-types";
|
||||
|
||||
declare namespace ExcalidrawLib {
|
||||
type ElementUpdate<TElement extends ExcalidrawElement> = Omit<
|
||||
Partial<TElement>,
|
||||
"id" | "version" | "versionNonce"
|
||||
>;
|
||||
|
||||
type ExportOpts = {
|
||||
elements: readonly NonDeleted<ExcalidrawElement>[];
|
||||
appState?: Partial<Omit<AppState, "offsetTop" | "offsetLeft">>;
|
||||
files: BinaryFiles | null;
|
||||
maxWidthOrHeight?: number;
|
||||
getDimensions?: (
|
||||
width: number,
|
||||
height: number,
|
||||
) => { width: number; height: number; scale?: number };
|
||||
};
|
||||
|
||||
function restore(
|
||||
data: Pick<ImportedDataState, "appState" | "elements" | "files"> | null,
|
||||
localAppState: Partial<AppState> | null | undefined,
|
||||
localElements: readonly ExcalidrawElement[] | null | undefined,
|
||||
elementsConfig?: { refreshDimensions?: boolean; repairBindings?: boolean },
|
||||
): RestoredDataState;
|
||||
|
||||
function exportToSvg(opts: Omit<ExportOpts, "getDimensions"> & {
|
||||
elements: ExcalidrawElement[];
|
||||
appState?: AppState;
|
||||
files?: any;
|
||||
exportPadding?: number;
|
||||
renderEmbeddables?: boolean;
|
||||
}): Promise<SVGSVGElement>;
|
||||
|
||||
function sceneCoordsToViewportCoords(
|
||||
sceneCoords: { sceneX: number; sceneY: number },
|
||||
viewParams: {
|
||||
zoom: Zoom;
|
||||
offsetLeft: number;
|
||||
offsetTop: number;
|
||||
scrollX: number;
|
||||
scrollY: number;
|
||||
},
|
||||
): { x: number; y: number };
|
||||
|
||||
function viewportCoordsToSceneCoords(
|
||||
viewportCoords: { clientX: number; clientY: number },
|
||||
viewParams: {
|
||||
zoom: Zoom;
|
||||
offsetLeft: number;
|
||||
offsetTop: number;
|
||||
scrollX: number;
|
||||
scrollY: number;
|
||||
},
|
||||
): { x: number; y: number };
|
||||
|
||||
function determineFocusDistance(
|
||||
element: ExcalidrawBindableElement,
|
||||
a: Point,
|
||||
b: Point,
|
||||
): number;
|
||||
|
||||
function intersectElementWithLine(
|
||||
element: ExcalidrawBindableElement,
|
||||
a: Point,
|
||||
b: Point,
|
||||
gap?: number,
|
||||
): Point[];
|
||||
|
||||
function getCommonBoundingBox(
|
||||
elements: ExcalidrawElement[] | readonly NonDeleted<ExcalidrawElement>[],
|
||||
): BoundingBox;
|
||||
|
||||
function getMaximumGroups(
|
||||
elements: ExcalidrawElement[],
|
||||
): ExcalidrawElement[][];
|
||||
|
||||
function measureText(
|
||||
text: string,
|
||||
font: FontString,
|
||||
lineHeight: number,
|
||||
): { width: number; height: number; baseline: number };
|
||||
|
||||
function getDefaultLineHeight(fontFamily: FontFamilyValues): number;
|
||||
|
||||
function wrapText(text: string, font: FontString, maxWidth: number): string;
|
||||
|
||||
function getFontString({
|
||||
fontSize,
|
||||
fontFamily,
|
||||
}: {
|
||||
fontSize: number;
|
||||
fontFamily: FontFamilyValues;
|
||||
}): FontString;
|
||||
|
||||
function getBoundTextMaxWidth(container: ExcalidrawElement): number;
|
||||
|
||||
function exportToBlob(
|
||||
opts: ExportOpts & {
|
||||
mimeType?: string;
|
||||
quality?: number;
|
||||
exportPadding?: number;
|
||||
},
|
||||
): Promise<Blob>;
|
||||
|
||||
function mutateElement<TElement extends Mutable<ExcalidrawElement>>(
|
||||
element: TElement,
|
||||
updates: ElementUpdate<TElement>,
|
||||
informMutation?: boolean,
|
||||
): TElement;
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
MarkdownView,
|
||||
request,
|
||||
requireApiVersion,
|
||||
WorkspaceSplit,
|
||||
} from "obsidian";
|
||||
//import * as React from "react";
|
||||
//import * as ReactDOM from "react-dom";
|
||||
@@ -49,6 +48,7 @@ import {
|
||||
EXPORT_IMG_ICON_NAME,
|
||||
viewportCoordsToSceneCoords,
|
||||
ERROR_IFRAME_CONVERSION_CANCELED,
|
||||
restore,
|
||||
} from "./Constants";
|
||||
import ExcalidrawPlugin from "./main";
|
||||
import {
|
||||
@@ -774,6 +774,18 @@ export default class ExcalidrawView extends TextFileView {
|
||||
new Notice(newState ? "Inverted Mode: Default arrow binding is now disabled. Use CTRL/CMD to temporarily enable binding when needed." : "Normal Mode: Arrow binding is now enabled. Use CTRL/CMD to temporarily disable binding when needed.");
|
||||
}
|
||||
|
||||
toggleFrameRendering() {
|
||||
const frameRenderingSt = (this.excalidrawAPI as ExcalidrawImperativeAPI).getAppState().frameRendering;
|
||||
this.updateScene({appState: {frameRendering: {...frameRenderingSt, enabled: !frameRenderingSt.enabled}}});
|
||||
new Notice(frameRenderingSt.enabled ? "Frame Rendering: Enabled" : "Frame Rendering: Disabled");
|
||||
}
|
||||
|
||||
toggleFrameClipping() {
|
||||
const frameRenderingSt = (this.excalidrawAPI as ExcalidrawImperativeAPI).getAppState().frameRendering;
|
||||
this.updateScene({appState: {frameRendering: {...frameRenderingSt, clip: !frameRenderingSt.clip}}});
|
||||
new Notice(frameRenderingSt.clip ? "Frame Clipping: Enabled" : "Frame Clipping: Disabled");
|
||||
}
|
||||
|
||||
gotoFullscreen() {
|
||||
if(this.plugin.leafChangeTimeout) {
|
||||
clearTimeout(this.plugin.leafChangeTimeout);
|
||||
@@ -2773,6 +2785,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
colorPalette: st.colorPalette,
|
||||
currentStrokeOptions: st.currentStrokeOptions,
|
||||
previousGridSize: st.previousGridSize,
|
||||
frameRendering: st.frameRendering,
|
||||
},
|
||||
prevTextMode: this.prevTextMode,
|
||||
files,
|
||||
@@ -4337,15 +4350,15 @@ export default class ExcalidrawView extends TextFileView {
|
||||
files?: any;
|
||||
commitToHistory?: boolean;
|
||||
},
|
||||
restore: boolean = false,
|
||||
shouldRestore: boolean = false,
|
||||
) {
|
||||
const api = this.excalidrawAPI;
|
||||
if (!api) {
|
||||
return;
|
||||
}
|
||||
const shouldRestoreElements = scene.elements && restore;
|
||||
const shouldRestoreElements = scene.elements && shouldRestore;
|
||||
if (shouldRestoreElements) {
|
||||
scene.elements = api.restore(scene).elements;
|
||||
scene.elements = restore(scene, null, null).elements;
|
||||
}
|
||||
try {
|
||||
api.updateScene(scene);
|
||||
@@ -4360,7 +4373,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
if (!shouldRestoreElements) {
|
||||
//second attempt
|
||||
try {
|
||||
scene.elements = api.restore(scene).elements;
|
||||
scene.elements = restore(scene, null, null).elements;
|
||||
api.updateScene(scene);
|
||||
} catch (e) {
|
||||
errorlog({
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { customAlphabet } from "nanoid";
|
||||
import { DeviceType } from "./types";
|
||||
import { Platform } from "obsidian";
|
||||
import { ExcalidrawLib } from "./ExcalidrawLib";
|
||||
//This is only for backward compatibility because an early version of obsidian included an encoding to avoid fantom links from littering Obsidian graph view
|
||||
declare const PLUGIN_VERSION:string;
|
||||
|
||||
export const ERROR_IFRAME_CONVERSION_CANCELED = "iframe conversion canceled";
|
||||
|
||||
declare const excalidrawLib: typeof ExcalidrawLib;
|
||||
|
||||
export const {
|
||||
sceneCoordsToViewportCoords,
|
||||
viewportCoordsToSceneCoords,
|
||||
@@ -21,7 +24,7 @@ export const {
|
||||
exportToSvg,
|
||||
exportToBlob,
|
||||
mutateElement,
|
||||
//@ts-ignore
|
||||
restore,
|
||||
} = excalidrawLib;
|
||||
|
||||
export function JSON_parse(x: string): any {
|
||||
|
||||
@@ -17,6 +17,8 @@ I develop this plugin as a hobby, spending my free time doing this. If you find
|
||||
|
||||
<div class="ex-coffee-div"><a href="https://ko-fi.com/zsolt"><img src="https://cdn.ko-fi.com/cdn/kofi3.png?v=3" height=45></a></div>
|
||||
`,
|
||||
"1.9.11":`
|
||||
`,
|
||||
"1.9.10":`
|
||||
## New
|
||||
- @mazurov added a new script: [Ellipse Selected Elements](https://github.com/zsviczian/obsidian-excalidraw-plugin/blob/master/ea-scripts/Ellipse%20Selected%20Elements.md)
|
||||
|
||||
@@ -507,6 +507,8 @@ FILENAME_HEAD: "Filename",
|
||||
EXIT_FULLSCREEN: "Exit fullscreen mode",
|
||||
TOGGLE_FULLSCREEN: "Toggle fullscreen mode",
|
||||
TOGGLE_DISABLEBINDING: "Toggle to invert default binding behavior",
|
||||
TOGGLE_FRAME_RENDERING: "Toggle frame rendering",
|
||||
TOGGLE_FRAME_CLIPPING: "Toggle frame clipping",
|
||||
OPEN_LINK_CLICK: "Navigate to selected element link",
|
||||
OPEN_LINK_PROPS: "Open markdown-embed properties or open link in new window",
|
||||
|
||||
|
||||
37
src/main.ts
37
src/main.ts
@@ -1019,6 +1019,43 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
},
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: "disable-framerendering",
|
||||
name: t("TOGGLE_FRAME_RENDERING"),
|
||||
checkCallback: (checking: boolean) => {
|
||||
if (checking) {
|
||||
return (
|
||||
Boolean(this.app.workspace.getActiveViewOfType(ExcalidrawView))
|
||||
);
|
||||
}
|
||||
const view = this.app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
if (view) {
|
||||
view.toggleFrameRendering();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: "disable-frameclipping",
|
||||
name: t("TOGGLE_FRAME_CLIPPING"),
|
||||
checkCallback: (checking: boolean) => {
|
||||
if (checking) {
|
||||
return (
|
||||
Boolean(this.app.workspace.getActiveViewOfType(ExcalidrawView))
|
||||
);
|
||||
}
|
||||
const view = this.app.workspace.getActiveViewOfType(ExcalidrawView);
|
||||
if (view) {
|
||||
view.toggleFrameClipping();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
this.addCommand({
|
||||
id: "export-image",
|
||||
name: t("EXPORT_IMAGE"),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { GITHUB_RELEASES } from "src/Constants";
|
||||
import { ExcalidrawGenericElement } from "./ExcalidrawElement";
|
||||
|
||||
declare const PLUGIN_VERSION:string;
|
||||
|
||||
class ExcalidrawScene {
|
||||
|
||||
@@ -25,9 +25,10 @@ import { ExcalidrawElement } from "@zsviczian/excalidraw/types/element/types";
|
||||
import { ExportSettings } from "../ExcalidrawView";
|
||||
import { compressToBase64, decompressFromBase64 } from "lz-string";
|
||||
import { getDataURLFromURL, getIMGFilename, getMimeType, getURLImageExtension } from "./FileUtils";
|
||||
import ExcalidrawScene from "../svgToExcalidraw/elements/ExcalidrawScene";
|
||||
import { IMAGE_TYPES } from "../Constants";
|
||||
import { generateEmbeddableLink } from "./CustomEmbeddableUtils";
|
||||
import Scene from "@zsviczian/excalidraw/types/scene/Scene";
|
||||
import ExcalidrawScene from "src/svgToExcalidraw/elements/ExcalidrawScene";
|
||||
|
||||
declare const PLUGIN_VERSION:string;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user