mirror of
https://github.com/zsviczian/obsidian-excalidraw-plugin.git
synced 2025-08-06 05:46:28 +00:00
improved new link handling
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
"@types/js-beautify": "^1.13.3",
|
||||
"@types/node": "^15.12.4",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@popperjs/core": "^2.11.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"html2canvas": "^1.4.0",
|
||||
"nanoid": "^3.1.31",
|
||||
|
||||
@@ -62,7 +62,7 @@ import {
|
||||
svgToBase64,
|
||||
viewportCoordsToSceneCoords,
|
||||
} from "./Utils";
|
||||
import { Prompt } from "./Prompt";
|
||||
import { NewFileActions, Prompt } from "./Prompt";
|
||||
import { ClipboardData } from "@zsviczian/excalidraw/types/clipboard";
|
||||
import { updateEquation } from "./LaTeX";
|
||||
import {
|
||||
@@ -464,10 +464,6 @@ export default class ExcalidrawView extends TextFileView {
|
||||
linkText,
|
||||
view.file.path,
|
||||
);
|
||||
if (!ev.altKey && !file) {
|
||||
new Notice(t("FILE_DOES_NOT_EXIST"), 4000);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const selectedImage = this.getSelectedImageElement();
|
||||
if (selectedImage?.id) {
|
||||
@@ -526,7 +522,7 @@ export default class ExcalidrawView extends TextFileView {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!linkText) {
|
||||
new Notice(t("LINK_BUTTON_CLICK_NO_TEXT"), 20000);
|
||||
return;
|
||||
@@ -536,15 +532,15 @@ export default class ExcalidrawView extends TextFileView {
|
||||
if (ev.shiftKey && this.isFullscreen()) {
|
||||
this.exitFullscreen();
|
||||
}
|
||||
if (!file) {
|
||||
(new NewFileActions(this.plugin,linkText,ev.shiftKey,view)).open();
|
||||
return;
|
||||
}
|
||||
const leaf = ev.shiftKey
|
||||
? getNewOrAdjacentLeaf(this.plugin, view.leaf)
|
||||
: view.leaf;
|
||||
view.app.workspace.setActiveLeaf(leaf);
|
||||
if (file) {
|
||||
leaf.openFile(file, { eState: { line: lineNum - 1 } }); //if file exists open file and jump to reference
|
||||
} else {
|
||||
leaf.view.app.workspace.openLinkText(linkText, view.file.path);
|
||||
}
|
||||
leaf.openFile(file, { eState: { line: lineNum - 1 } }); //if file exists open file and jump to reference
|
||||
view.app.workspace.setActiveLeaf(leaf,true,true);
|
||||
} catch (e) {
|
||||
new Notice(e, 4000);
|
||||
}
|
||||
|
||||
460
src/FolderSuggester.ts
Normal file
460
src/FolderSuggester.ts
Normal file
@@ -0,0 +1,460 @@
|
||||
import {
|
||||
FuzzyMatch,
|
||||
TFile,
|
||||
BlockCache,
|
||||
HeadingCache,
|
||||
CachedMetadata,
|
||||
TextComponent,
|
||||
App,
|
||||
TFolder,
|
||||
FuzzySuggestModal,
|
||||
SuggestModal,
|
||||
Scope
|
||||
} from "obsidian";
|
||||
import { t } from "./lang/helpers";
|
||||
import { createPopper, Instance as PopperInstance } from "@popperjs/core";
|
||||
|
||||
class Suggester<T> {
|
||||
owner: SuggestModal<T>;
|
||||
items: T[];
|
||||
suggestions: HTMLDivElement[];
|
||||
selectedItem: number;
|
||||
containerEl: HTMLElement;
|
||||
constructor(
|
||||
owner: SuggestModal<T>,
|
||||
containerEl: HTMLElement,
|
||||
scope: Scope
|
||||
) {
|
||||
this.containerEl = containerEl;
|
||||
this.owner = owner;
|
||||
containerEl.on(
|
||||
"click",
|
||||
".suggestion-item",
|
||||
this.onSuggestionClick.bind(this)
|
||||
);
|
||||
containerEl.on(
|
||||
"mousemove",
|
||||
".suggestion-item",
|
||||
this.onSuggestionMouseover.bind(this)
|
||||
);
|
||||
|
||||
scope.register([], "ArrowUp", () => {
|
||||
this.setSelectedItem(this.selectedItem - 1, true);
|
||||
return false;
|
||||
});
|
||||
|
||||
scope.register([], "ArrowDown", () => {
|
||||
this.setSelectedItem(this.selectedItem + 1, true);
|
||||
return false;
|
||||
});
|
||||
|
||||
scope.register([], "Enter", (evt) => {
|
||||
this.useSelectedItem(evt);
|
||||
return false;
|
||||
});
|
||||
|
||||
scope.register([], "Tab", (evt) => {
|
||||
this.chooseSuggestion(evt);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
chooseSuggestion(evt: KeyboardEvent) {
|
||||
if (!this.items || !this.items.length) return;
|
||||
const currentValue = this.items[this.selectedItem];
|
||||
if (currentValue) {
|
||||
this.owner.onChooseSuggestion(currentValue, evt);
|
||||
}
|
||||
}
|
||||
onSuggestionClick(event: MouseEvent, el: HTMLDivElement): void {
|
||||
event.preventDefault();
|
||||
if (!this.suggestions || !this.suggestions.length) return;
|
||||
|
||||
const item = this.suggestions.indexOf(el);
|
||||
this.setSelectedItem(item, false);
|
||||
this.useSelectedItem(event);
|
||||
}
|
||||
|
||||
onSuggestionMouseover(event: MouseEvent, el: HTMLDivElement): void {
|
||||
if (!this.suggestions || !this.suggestions.length) return;
|
||||
const item = this.suggestions.indexOf(el);
|
||||
this.setSelectedItem(item, false);
|
||||
}
|
||||
empty() {
|
||||
this.containerEl.empty();
|
||||
}
|
||||
setSuggestions(items: T[]) {
|
||||
this.containerEl.empty();
|
||||
const els: HTMLDivElement[] = [];
|
||||
|
||||
items.forEach((item) => {
|
||||
const suggestionEl = this.containerEl.createDiv("suggestion-item");
|
||||
this.owner.renderSuggestion(item, suggestionEl);
|
||||
els.push(suggestionEl);
|
||||
});
|
||||
this.items = items;
|
||||
this.suggestions = els;
|
||||
this.setSelectedItem(0, false);
|
||||
}
|
||||
useSelectedItem(event: MouseEvent | KeyboardEvent) {
|
||||
if (!this.items || !this.items.length) return;
|
||||
const currentValue = this.items[this.selectedItem];
|
||||
if (currentValue) {
|
||||
this.owner.selectSuggestion(currentValue, event);
|
||||
}
|
||||
}
|
||||
wrap(value: number, size: number): number {
|
||||
return ((value % size) + size) % size;
|
||||
}
|
||||
setSelectedItem(index: number, scroll: boolean) {
|
||||
const nIndex = this.wrap(index, this.suggestions.length);
|
||||
const prev = this.suggestions[this.selectedItem];
|
||||
const next = this.suggestions[nIndex];
|
||||
|
||||
if (prev) prev.removeClass("is-selected");
|
||||
if (next) next.addClass("is-selected");
|
||||
|
||||
this.selectedItem = nIndex;
|
||||
|
||||
if (scroll) {
|
||||
next.scrollIntoView(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class SuggestionModal<T> extends FuzzySuggestModal<T> {
|
||||
items: T[] = [];
|
||||
suggestions: HTMLDivElement[];
|
||||
popper: PopperInstance;
|
||||
//@ts-ignore
|
||||
scope: Scope = new Scope(this.app.scope);
|
||||
suggester: Suggester<FuzzyMatch<T>>;
|
||||
suggestEl: HTMLDivElement;
|
||||
promptEl: HTMLDivElement;
|
||||
emptyStateText: string = "No match found";
|
||||
limit: number = 100;
|
||||
shouldNotOpen: boolean;
|
||||
constructor(app: App, inputEl: HTMLInputElement, items: T[]) {
|
||||
super(app);
|
||||
this.inputEl = inputEl;
|
||||
this.items = items;
|
||||
|
||||
this.suggestEl = createDiv("suggestion-container");
|
||||
|
||||
this.contentEl = this.suggestEl.createDiv("suggestion");
|
||||
|
||||
this.suggester = new Suggester(this, this.contentEl, this.scope);
|
||||
|
||||
this.scope.register([], "Escape", this.onEscape.bind(this));
|
||||
|
||||
this.inputEl.addEventListener("input", this.onInputChanged.bind(this));
|
||||
this.inputEl.addEventListener("focus", this.onFocus.bind(this));
|
||||
this.inputEl.addEventListener("blur", this.close.bind(this));
|
||||
this.suggestEl.on(
|
||||
"mousedown",
|
||||
".suggestion-container",
|
||||
(event: MouseEvent) => {
|
||||
event.preventDefault();
|
||||
}
|
||||
);
|
||||
}
|
||||
empty() {
|
||||
this.suggester.empty();
|
||||
}
|
||||
onInputChanged(): void {
|
||||
if (this.shouldNotOpen) return;
|
||||
const inputStr = this.modifyInput(this.inputEl.value);
|
||||
const suggestions = this.getSuggestions(inputStr);
|
||||
if (suggestions.length > 0) {
|
||||
this.suggester.setSuggestions(suggestions.slice(0, this.limit));
|
||||
} else {
|
||||
this.onNoSuggestion();
|
||||
}
|
||||
this.open();
|
||||
}
|
||||
onFocus(): void {
|
||||
this.shouldNotOpen = false;
|
||||
this.onInputChanged();
|
||||
}
|
||||
modifyInput(input: string): string {
|
||||
return input;
|
||||
}
|
||||
onNoSuggestion() {
|
||||
this.empty();
|
||||
this.renderSuggestion(
|
||||
null,
|
||||
this.contentEl.createDiv("suggestion-item")
|
||||
);
|
||||
}
|
||||
open(): void {
|
||||
// TODO: Figure out a better way to do this. Idea from Periodic Notes plugin
|
||||
this.app.keymap.pushScope(this.scope);
|
||||
|
||||
document.body.appendChild(this.suggestEl);
|
||||
this.popper = createPopper(this.inputEl, this.suggestEl, {
|
||||
placement: "bottom-start",
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, 10]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "flip",
|
||||
options: {
|
||||
fallbackPlacements: ["top"]
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
onEscape(): void {
|
||||
this.close();
|
||||
this.shouldNotOpen = true;
|
||||
}
|
||||
close(): void {
|
||||
// TODO: Figure out a better way to do this. Idea from Periodic Notes plugin
|
||||
this.app.keymap.popScope(this.scope);
|
||||
|
||||
this.suggester.setSuggestions([]);
|
||||
if (this.popper) {
|
||||
this.popper.destroy();
|
||||
}
|
||||
|
||||
this.suggestEl.detach();
|
||||
}
|
||||
createPrompt(prompts: HTMLSpanElement[]) {
|
||||
if (!this.promptEl)
|
||||
this.promptEl = this.suggestEl.createDiv("prompt-instructions");
|
||||
let prompt = this.promptEl.createDiv("prompt-instruction");
|
||||
for (let p of prompts) {
|
||||
prompt.appendChild(p);
|
||||
}
|
||||
}
|
||||
abstract onChooseItem(item: T, evt: MouseEvent | KeyboardEvent): void;
|
||||
abstract getItemText(arg: T): string;
|
||||
abstract getItems(): T[];
|
||||
}
|
||||
|
||||
export class PathSuggestionModal extends SuggestionModal<
|
||||
TFile | BlockCache | HeadingCache
|
||||
> {
|
||||
file: TFile;
|
||||
files: TFile[];
|
||||
text: TextComponent;
|
||||
cache: CachedMetadata;
|
||||
constructor(app: App, input: TextComponent, items: TFile[]) {
|
||||
super(app, input.inputEl, items);
|
||||
this.files = [...items];
|
||||
this.text = input;
|
||||
//this.getFile();
|
||||
|
||||
|
||||
this.inputEl.addEventListener("input", this.getFile.bind(this));
|
||||
}
|
||||
|
||||
getFile() {
|
||||
const v = this.inputEl.value,
|
||||
file = this.app.metadataCache.getFirstLinkpathDest(
|
||||
v.split(/[\^#]/).shift() || "",
|
||||
""
|
||||
);
|
||||
if (file == this.file) return;
|
||||
this.file = file;
|
||||
if (this.file)
|
||||
this.cache = this.app.metadataCache.getFileCache(this.file);
|
||||
this.onInputChanged();
|
||||
}
|
||||
getItemText(item: TFile | HeadingCache | BlockCache) {
|
||||
if (item instanceof TFile) return item.path;
|
||||
if (Object.prototype.hasOwnProperty.call(item, "heading")) {
|
||||
return (<HeadingCache>item).heading;
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(item, "id")) {
|
||||
return (<BlockCache>item).id;
|
||||
}
|
||||
}
|
||||
onChooseItem(item: TFile | HeadingCache | BlockCache) {
|
||||
if (item instanceof TFile) {
|
||||
this.text.setValue(item.basename);
|
||||
this.file = item;
|
||||
this.cache = this.app.metadataCache.getFileCache(this.file);
|
||||
} else if (Object.prototype.hasOwnProperty.call(item, "heading")) {
|
||||
this.text.setValue(
|
||||
this.file.basename + "#" + (<HeadingCache>item).heading
|
||||
);
|
||||
} else if (Object.prototype.hasOwnProperty.call(item, "id")) {
|
||||
this.text.setValue(
|
||||
this.file.basename + "^" + (<BlockCache>item).id
|
||||
);
|
||||
}
|
||||
}
|
||||
selectSuggestion({ item }: FuzzyMatch<TFile | BlockCache | HeadingCache>) {
|
||||
let link: string;
|
||||
if (item instanceof TFile) {
|
||||
link = item.basename;
|
||||
} else if (Object.prototype.hasOwnProperty.call(item, "heading")) {
|
||||
link = this.file.basename + "#" + (<HeadingCache>item).heading;
|
||||
} else if (Object.prototype.hasOwnProperty.call(item, "id")) {
|
||||
link = this.file.basename + "^" + (<BlockCache>item).id;
|
||||
}
|
||||
|
||||
this.text.setValue(link);
|
||||
this.onClose();
|
||||
|
||||
this.close();
|
||||
}
|
||||
renderSuggestion(
|
||||
result: FuzzyMatch<TFile | BlockCache | HeadingCache>,
|
||||
el: HTMLElement
|
||||
) {
|
||||
let { item, match: matches } = result || {};
|
||||
let content = el.createDiv({
|
||||
cls: "suggestion-content"
|
||||
});
|
||||
if (!item) {
|
||||
content.setText(this.emptyStateText);
|
||||
content.parentElement.addClass("is-selected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (item instanceof TFile) {
|
||||
let pathLength = item.path.length - item.name.length;
|
||||
const matchElements = matches.matches.map((m) => {
|
||||
return createSpan("suggestion-highlight");
|
||||
});
|
||||
for (
|
||||
let i = pathLength;
|
||||
i < item.path.length - item.extension.length - 1;
|
||||
i++
|
||||
) {
|
||||
let match = matches.matches.find((m) => m[0] === i);
|
||||
if (match) {
|
||||
let element = matchElements[matches.matches.indexOf(match)];
|
||||
content.appendChild(element);
|
||||
element.appendText(item.path.substring(match[0], match[1]));
|
||||
|
||||
i += match[1] - match[0] - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
content.appendText(item.path[i]);
|
||||
}
|
||||
el.createDiv({
|
||||
cls: "suggestion-note",
|
||||
text: item.path
|
||||
});
|
||||
} else if (Object.prototype.hasOwnProperty.call(item, "heading")) {
|
||||
content.setText((<HeadingCache>item).heading);
|
||||
content.prepend(
|
||||
createSpan({
|
||||
cls: "suggestion-flair",
|
||||
text: `H${(<HeadingCache>item).level}`
|
||||
})
|
||||
);
|
||||
} else if (Object.prototype.hasOwnProperty.call(item, "id")) {
|
||||
content.setText((<BlockCache>item).id);
|
||||
}
|
||||
}
|
||||
get headings() {
|
||||
if (!this.file) return [];
|
||||
if (!this.cache) {
|
||||
this.cache = this.app.metadataCache.getFileCache(this.file);
|
||||
}
|
||||
return this.cache.headings || [];
|
||||
}
|
||||
get blocks() {
|
||||
if (!this.file) return [];
|
||||
if (!this.cache) {
|
||||
this.cache = this.app.metadataCache.getFileCache(this.file);
|
||||
}
|
||||
return Object.values(this.cache.blocks || {}) || [];
|
||||
}
|
||||
getItems() {
|
||||
const v = this.inputEl.value;
|
||||
if (/#/.test(v)) {
|
||||
this.modifyInput = (i) => i.split(/#/).pop();
|
||||
return this.headings;
|
||||
} else if (/\^/.test(v)) {
|
||||
this.modifyInput = (i) => i.split(/\^/).pop();
|
||||
return this.blocks;
|
||||
}
|
||||
return this.files;
|
||||
}
|
||||
}
|
||||
|
||||
export class FolderSuggestionModal extends SuggestionModal<TFolder> {
|
||||
text: TextComponent;
|
||||
cache: CachedMetadata;
|
||||
folders: TFolder[];
|
||||
folder: TFolder;
|
||||
constructor(app: App, input: TextComponent, items: TFolder[]) {
|
||||
super(app, input.inputEl, items);
|
||||
this.folders = [...items];
|
||||
this.text = input;
|
||||
|
||||
this.inputEl.addEventListener("input", () => this.getFolder());
|
||||
}
|
||||
getFolder() {
|
||||
const v = this.inputEl.value,
|
||||
folder = this.app.vault.getAbstractFileByPath(v);
|
||||
if (folder == this.folder) return;
|
||||
if (!(folder instanceof TFolder)) return;
|
||||
this.folder = folder;
|
||||
|
||||
this.onInputChanged();
|
||||
}
|
||||
getItemText(item: TFolder) {
|
||||
return item.path;
|
||||
}
|
||||
onChooseItem(item: TFolder) {
|
||||
this.text.setValue(item.path);
|
||||
this.folder = item;
|
||||
}
|
||||
selectSuggestion({ item }: FuzzyMatch<TFolder>) {
|
||||
let link = item.path;
|
||||
|
||||
this.text.setValue(link);
|
||||
this.onClose();
|
||||
|
||||
this.close();
|
||||
}
|
||||
renderSuggestion(result: FuzzyMatch<TFolder>, el: HTMLElement) {
|
||||
let { item, match: matches } = result || {};
|
||||
let content = el.createDiv({
|
||||
cls: "suggestion-content"
|
||||
});
|
||||
if (!item) {
|
||||
content.setText(this.emptyStateText);
|
||||
content.parentElement.addClass("is-selected");
|
||||
return;
|
||||
}
|
||||
|
||||
let pathLength = item.path.length - item.name.length;
|
||||
const matchElements = matches.matches.map((m) => {
|
||||
return createSpan("suggestion-highlight");
|
||||
});
|
||||
for (let i = pathLength; i < item.path.length; i++) {
|
||||
let match = matches.matches.find((m) => m[0] === i);
|
||||
if (match) {
|
||||
let element = matchElements[matches.matches.indexOf(match)];
|
||||
content.appendChild(element);
|
||||
element.appendText(item.path.substring(match[0], match[1]));
|
||||
|
||||
i += match[1] - match[0] - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
content.appendText(item.path[i]);
|
||||
}
|
||||
el.createDiv({
|
||||
cls: "suggestion-note",
|
||||
text: item.path
|
||||
});
|
||||
}
|
||||
|
||||
getItems() {
|
||||
return this.folders;
|
||||
}
|
||||
}
|
||||
132
src/Prompt.ts
132
src/Prompt.ts
@@ -6,7 +6,11 @@ import {
|
||||
FuzzyMatch,
|
||||
FuzzySuggestModal,
|
||||
Instruction,
|
||||
TFile,
|
||||
} from "obsidian";
|
||||
import ExcalidrawView from "./ExcalidrawView";
|
||||
import ExcalidrawPlugin from "./main";
|
||||
import { getNewOrAdjacentLeaf } from "./Utils";
|
||||
|
||||
export class Prompt extends Modal {
|
||||
private promptEl: HTMLInputElement;
|
||||
@@ -281,3 +285,131 @@ export class GenericSuggester extends FuzzySuggestModal<any> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MigrationPrompt extends Modal {
|
||||
private plugin: ExcalidrawPlugin;
|
||||
|
||||
constructor(app: App, plugin: ExcalidrawPlugin) {
|
||||
super(app);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
onOpen(): void {
|
||||
this.titleEl.setText("Welcome to Excalidraw 1.2");
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
onClose(): void {
|
||||
this.contentEl.empty();
|
||||
}
|
||||
|
||||
createForm(): void {
|
||||
const div = this.contentEl.createDiv();
|
||||
// div.addClass("excalidraw-prompt-div");
|
||||
// div.style.maxWidth = "600px";
|
||||
div.createEl("p", {
|
||||
text: "This version comes with tons of new features and possibilities. Please read the description in Community Plugins to find out more.",
|
||||
});
|
||||
div.createEl("p", { text: "" }, (el) => {
|
||||
el.innerHTML =
|
||||
"Drawings you've created with version 1.1.x need to be converted to take advantage of the new features. You can also continue to use them in compatibility mode. " +
|
||||
"During conversion your old *.excalidraw files will be replaced with new *.excalidraw.md files.";
|
||||
});
|
||||
div.createEl("p", { text: "" }, (el) => {
|
||||
//files manually follow one of two options:
|
||||
el.innerHTML =
|
||||
"To convert your drawings you have the following options:<br><ul>" +
|
||||
"<li>Click <code>CONVERT FILES</code> now to convert all of your *.excalidraw files, or if you prefer to make a backup first, then click <code>CANCEL</code>.</li>" +
|
||||
"<li>In the Command Palette select <code>Excalidraw: Convert *.excalidraw files to *.excalidraw.md files</code></li>" +
|
||||
"<li>Right click an <code>*.excalidraw</code> file in File Explorer and select one of the following options to convert files one by one: <ul>" +
|
||||
"<li><code>*.excalidraw => *.excalidraw.md</code></li>" +
|
||||
"<li><code>*.excalidraw => *.md (Logseq compatibility)</code>. This option will retain the original *.excalidraw file next to the new Obsidian format. " +
|
||||
"Make sure you also enable <code>Compatibility features</code> in Settings for a full solution.</li></ul></li>" +
|
||||
"<li>Open a drawing in compatibility mode and select <code>Convert to new format</code> from the <code>Options Menu</code></li></ul>";
|
||||
});
|
||||
div.createEl("p", {
|
||||
text: "This message will only appear maximum 3 times in case you have *.excalidraw files in your Vault.",
|
||||
});
|
||||
const bConvert = div.createEl("button", { text: "CONVERT FILES" });
|
||||
bConvert.onclick = () => {
|
||||
this.plugin.convertExcalidrawToMD();
|
||||
this.close();
|
||||
};
|
||||
const bCancel = div.createEl("button", { text: "CANCEL" });
|
||||
bCancel.onclick = () => {
|
||||
this.close();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class NewFileActions extends Modal {
|
||||
constructor (
|
||||
private plugin: ExcalidrawPlugin,
|
||||
private path: string,
|
||||
private newPane: boolean,
|
||||
private view: ExcalidrawView,
|
||||
) {
|
||||
super(plugin.app);
|
||||
}
|
||||
|
||||
onOpen(): void {
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
async onClose() {
|
||||
}
|
||||
|
||||
openFile(file: TFile): void {
|
||||
if(!file) return;
|
||||
const leaf = this.newPane
|
||||
? getNewOrAdjacentLeaf(this.plugin, this.view.leaf)
|
||||
: this.view.leaf;
|
||||
leaf.openFile(file);
|
||||
this.app.workspace.setActiveLeaf(leaf, true, true);
|
||||
}
|
||||
|
||||
createForm(): void {
|
||||
this.titleEl.setText("New File");
|
||||
|
||||
this.contentEl.createDiv({
|
||||
cls: "excalidraw-prompt-center",
|
||||
text: "File does not exist. Do you want to create it?"
|
||||
});
|
||||
this.contentEl.createDiv({
|
||||
cls: "excalidraw-prompt-center filepath",
|
||||
text: this.path
|
||||
});
|
||||
|
||||
this.contentEl.createDiv({cls: "excalidraw-prompt-center"}, (el) => {
|
||||
//files manually follow one of two options:
|
||||
el.style.textAlign = "right";
|
||||
|
||||
const bMd = el.createEl("button", { text: "Create Markdown" });
|
||||
bMd.onclick = async () => {
|
||||
//@ts-ignore
|
||||
const f = await this.app.fileManager.createNewMarkdownFileFromLinktext(this.path,this.viewFile);
|
||||
this.openFile(f);
|
||||
this.close();
|
||||
};
|
||||
|
||||
|
||||
const bEx = el.createEl("button", { text: "Create Excalidraw" });
|
||||
bEx.onclick = async () => {
|
||||
//@ts-ignore
|
||||
const f = await this.app.fileManager.createNewMarkdownFileFromLinktext(this.path,this.viewFile)
|
||||
if(!f) return;
|
||||
await this.app.vault.modify(f,await this.plugin.getBlankDrawing());
|
||||
await new Promise(r => setTimeout(r, 200)); //wait for metadata cache to update, so file opens as excalidraw
|
||||
this.openFile(f);
|
||||
this.close();
|
||||
};
|
||||
|
||||
const bCancel = el.createEl("button", {
|
||||
text: "Never Mind",
|
||||
});
|
||||
bCancel.onclick = () => {
|
||||
this.close();
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1459,7 +1459,7 @@ export default class ExcalidrawPlugin extends Plugin {
|
||||
);
|
||||
}
|
||||
|
||||
private async getBlankDrawing(): Promise<string> {
|
||||
public async getBlankDrawing(): Promise<string> {
|
||||
const template = this.app.metadataCache.getFirstLinkpathDest(
|
||||
normalizePath(this.settings.templateFilePath),
|
||||
"",
|
||||
|
||||
10
styles.css
10
styles.css
@@ -134,4 +134,14 @@ li[data-testid] {
|
||||
|
||||
.excalidraw-scriptengine-install .modal {
|
||||
max-height:90%;
|
||||
}
|
||||
|
||||
.excalidraw-prompt-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.excalidraw-prompt-center.filepath {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
@@ -1355,6 +1355,11 @@
|
||||
"schema-utils" "^3.0.0"
|
||||
"source-map" "^0.7.3"
|
||||
|
||||
"@popperjs/core@^2.11.2":
|
||||
"integrity" "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA=="
|
||||
"resolved" "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz"
|
||||
"version" "2.11.2"
|
||||
|
||||
"@rollup/plugin-babel@^5.2.0", "@rollup/plugin-babel@^5.3.0":
|
||||
"integrity" "sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw=="
|
||||
"resolved" "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz"
|
||||
|
||||
Reference in New Issue
Block a user