cloudy9101_obsidian-image-i.../ModalWrapper.tsx
2025-09-16 22:46:44 +12:00

125 lines
3.4 KiB
TypeScript

import { upsert } from "meta-updater";
import { App, Editor, Notice, Modal } from "obsidian";
import * as React from "react";
import * as ReactDOM from "react-dom";
import { createRoot } from "react-dom/client";
import { getFetcher } from "./fetchers";
import { Fetcher, Image } from "./fetchers/constants";
import { ImagesModal } from "./ImagesModal";
import { ImageProvider, PluginSettings } from "./SettingTab";
export enum InsertPlace {
default = "default",
frontmatter = "frontmatter",
}
export class ModalWrapper extends Modal {
editor: Editor;
fetcher: ReturnType<typeof getFetcher>;
settings: PluginSettings;
insertPlace: InsertPlace;
random: boolean;
constructor(
app: App,
editor: Editor,
settings: PluginSettings,
insertPlace: InsertPlace = InsertPlace.default,
random = false,
) {
super(app);
this.editor = editor;
this.settings = {
...settings,
useMarkdownLinks: app.vault.config.useMarkdownLinks,
};
this.fetcher = getFetcher({ ...this.settings, imageProvider: random ? ImageProvider.unsplash : this.settings.imageProvider }, app.vault);
this.insertPlace = insertPlace;
this.random = random
this.containerEl.addClass("image-inserter-container");
}
onFetcherChange(fetcher: Fetcher) {
this.fetcher = fetcher;
}
async onOpen() {
const { contentEl } = this;
const root = createRoot(contentEl);
root.render(
<React.StrictMode>
<ImagesModal
fetcher={this.fetcher}
onFetcherChange={this.onFetcherChange.bind(this)}
settings={this.settings}
random={this.random}
onSelect={this.onChooseSuggestion.bind(this)}
/>
</React.StrictMode>,
);
}
onClose() {
const { containerEl } = this;
ReactDOM.unmountComponentAtNode(containerEl);
containerEl.empty();
}
async createFile(name: string, ext: string, binary: ArrayBuffer) {
const file = this.app.workspace.getActiveFile();
if (file === null) {
throw "No active file";
}
const filePath = await this.app.vault.getAvailablePathForAttachments(
name,
ext,
file,
);
this.app.vault.createBinary(filePath, binary);
}
async onChooseSuggestion(item: Image) {
try {
if (this.insertPlace === InsertPlace.default) {
const imageTag = await this.fetcher.downloadAndInsertImage(
item,
this.createFile.bind(this),
);
this.editor.replaceSelection(imageTag);
}
if (this.insertPlace === InsertPlace.frontmatter) {
const { url: imageTag, referral } =
await this.fetcher.downloadAndGetUri(
item,
this.createFile.bind(this),
);
const file = this.app.workspace.getActiveFile();
if (file) {
const updatedContent = await upsert(
this.app,
file,
this.settings.frontmatter.key,
`"${this.settings.frontmatter.valueFormat.replace(
"{image-url}",
imageTag,
)}"`,
);
await this.app.vault.modify(
file,
this.settings.frontmatter.appendReferral
? [updatedContent, referral].join("\n")
: updatedContent,
);
}
}
this.close();
} catch (e) {
console.error(e);
new Notice("Something went wrong, please contact the plugin author.");
}
}
}