mirror of
https://github.com/4513echo/obsidian-embed-plus.git
synced 2026-07-22 17:20:32 +00:00
fix: Store src in EmbedSource itself
This commit is contained in:
parent
e41c110c33
commit
db0a16edff
4 changed files with 31 additions and 34 deletions
|
|
@ -3,16 +3,16 @@ import type { EditorView, WidgetType } from "@codemirror/view";
|
|||
|
||||
export type WidgetInit =
|
||||
| { state: "resolving"; url: string }
|
||||
| { state: "resolved"; url: string; src: string }
|
||||
| { state: "resolved"; url: string }
|
||||
| { state: "loaded"; url: string }
|
||||
| { state: "failed"; url: string; error: Error };
|
||||
|
||||
const resolvedEffect = StateEffect.define<{ url: string; src: string }>();
|
||||
const resolvedEffect = StateEffect.define<{ url: string }>();
|
||||
const failedEffect = StateEffect.define<{ url: string; error: Error }>();
|
||||
const loadedEffect = StateEffect.define<{ url: string }>();
|
||||
|
||||
export function resolved(view: EditorView, url: string, src: string): void {
|
||||
view.dispatch({ effects: resolvedEffect.of({ url, src }) });
|
||||
export function resolved(view: EditorView, url: string): void {
|
||||
view.dispatch({ effects: resolvedEffect.of({ url }) });
|
||||
}
|
||||
|
||||
export function failed(view: EditorView, url: string, error: Error): void {
|
||||
|
|
@ -29,10 +29,7 @@ export function* constructWidget<T extends WidgetType>(
|
|||
): Generator<[string, T]> {
|
||||
for (const effect of effects) {
|
||||
if (effect.is(resolvedEffect)) {
|
||||
yield [
|
||||
effect.value.url,
|
||||
new widget({ state: "resolved", url: effect.value.url, src: effect.value.src }),
|
||||
];
|
||||
yield [effect.value.url, new widget({ state: "resolved", url: effect.value.url })];
|
||||
} else if (effect.is(failedEffect)) {
|
||||
yield [
|
||||
effect.value.url,
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ export abstract class EmbedSource {
|
|||
constructor(url: string) {
|
||||
this.url = url;
|
||||
}
|
||||
abstract render(src: string): HTMLElement;
|
||||
abstract resolveSrc(): string | Promise<string>;
|
||||
abstract render(): HTMLElement;
|
||||
resolveSrc(): void | Promise<void> {}
|
||||
get height(): number | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ export class Bluesky extends EmbedSource {
|
|||
static #heightCache: Map<string, number> = new Map();
|
||||
static id = 0;
|
||||
#id = (Bluesky.id++).toString();
|
||||
#src?: string;
|
||||
constructor(url: string) {
|
||||
super(url);
|
||||
}
|
||||
|
|
@ -61,7 +62,7 @@ export class Bluesky extends EmbedSource {
|
|||
};
|
||||
}
|
||||
|
||||
render(src: string): HTMLElement {
|
||||
render(): HTMLElement {
|
||||
const searchParams = new URLSearchParams({
|
||||
id: this.#id,
|
||||
colorMode: document.body.classList.contains("theme-dark") ? "dark" : "light",
|
||||
|
|
@ -69,7 +70,7 @@ export class Bluesky extends EmbedSource {
|
|||
const iframe = createEl("iframe", {
|
||||
cls: ["external-embed", "node-insert-event"],
|
||||
attr: {
|
||||
src: src + "?" + searchParams.toString(),
|
||||
src: this.#src + "?" + searchParams.toString(),
|
||||
loading: "lazy",
|
||||
"data-bluesky-id": this.#id,
|
||||
},
|
||||
|
|
@ -80,8 +81,13 @@ export class Bluesky extends EmbedSource {
|
|||
return iframe;
|
||||
}
|
||||
|
||||
override resolveSrc(): string | Promise<string> {
|
||||
return resolveEmbedSrc(this.url);
|
||||
override resolveSrc(): void | Promise<void> {
|
||||
if (this.#src) {
|
||||
return;
|
||||
}
|
||||
return resolveEmbedSrc(this.url).then((src) => {
|
||||
this.#src = src;
|
||||
});
|
||||
}
|
||||
|
||||
override get height(): number | undefined {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ function Container(url: string, state: WidgetInit["state"]): HTMLElement {
|
|||
export class EmbedWidget extends WidgetType {
|
||||
#url: string;
|
||||
#state: WidgetInit["state"];
|
||||
#src?: string;
|
||||
#error?: Error;
|
||||
#embedSource: EmbedSource;
|
||||
constructor(init: WidgetInit) {
|
||||
|
|
@ -38,9 +37,6 @@ export class EmbedWidget extends WidgetType {
|
|||
this.#url = init.url;
|
||||
this.#state = init.state;
|
||||
switch (init.state) {
|
||||
case "resolved":
|
||||
this.#src = init.src;
|
||||
break;
|
||||
case "failed":
|
||||
this.#error = init.error;
|
||||
break;
|
||||
|
|
@ -58,24 +54,23 @@ export class EmbedWidget extends WidgetType {
|
|||
switch (this.#state) {
|
||||
case "resolving":
|
||||
container.appendChild(Loading(this.#embedSource.height));
|
||||
const srcOrPromise = this.#embedSource.resolveSrc();
|
||||
if (srcOrPromise instanceof Promise) {
|
||||
srcOrPromise
|
||||
.then((src) => resolved(view, this.#url, src))
|
||||
const needResolve = this.#embedSource.resolveSrc();
|
||||
if (needResolve instanceof Promise) {
|
||||
needResolve
|
||||
.then(() => resolved(view, this.#url))
|
||||
.catch((error) => failed(view, this.#url, error));
|
||||
} else {
|
||||
this.#state = "resolved";
|
||||
this.#src = srcOrPromise;
|
||||
container.setAttribute("data-state", "resolved");
|
||||
container.appendChild(this.#embedSource.render(this.#src!));
|
||||
container.appendChild(this.#embedSource.render());
|
||||
}
|
||||
break;
|
||||
case "resolved":
|
||||
container.appendChild(Loading(this.#embedSource.height));
|
||||
container.appendChild(this.#embedSource.render(this.#src!));
|
||||
container.appendChild(this.#embedSource.render());
|
||||
break;
|
||||
case "loaded":
|
||||
container.appendChild(this.#embedSource.render(this.#src!));
|
||||
container.appendChild(this.#embedSource.render());
|
||||
break;
|
||||
case "failed":
|
||||
container.appendChild(ErrorMessage(this.#error!));
|
||||
|
|
@ -102,7 +97,7 @@ export class EmbedWidget extends WidgetType {
|
|||
case "resolving":
|
||||
return false;
|
||||
case "resolved":
|
||||
dom.appendChild(this.#embedSource.render(this.#src!));
|
||||
dom.appendChild(this.#embedSource.render());
|
||||
return true;
|
||||
case "loaded":
|
||||
const iframe = dom.querySelector("iframe");
|
||||
|
|
@ -119,7 +114,6 @@ export class EmbedWidget extends WidgetType {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: use "loading" state
|
||||
export function createElement(url: string, dom: HTMLElement): void {
|
||||
const embedSource = EmbedSourceRegistry.lookup(url);
|
||||
if (!embedSource) {
|
||||
|
|
@ -136,12 +130,12 @@ export function createElement(url: string, dom: HTMLElement): void {
|
|||
}
|
||||
loading.remove();
|
||||
});
|
||||
const srcOrPromise = embedSource.resolveSrc();
|
||||
if (srcOrPromise instanceof Promise) {
|
||||
srcOrPromise
|
||||
.then((src) => {
|
||||
const needResolve = embedSource.resolveSrc();
|
||||
if (needResolve instanceof Promise) {
|
||||
needResolve
|
||||
.then(() => {
|
||||
container.setAttribute("data-state", "resolved");
|
||||
container.appendChild(embedSource.render(src));
|
||||
container.appendChild(embedSource.render());
|
||||
})
|
||||
.catch((error) => {
|
||||
container.setAttribute("data-state", "failed");
|
||||
|
|
@ -149,7 +143,7 @@ export function createElement(url: string, dom: HTMLElement): void {
|
|||
loading.remove();
|
||||
});
|
||||
} else {
|
||||
container.appendChild(embedSource.render(srcOrPromise));
|
||||
container.appendChild(embedSource.render());
|
||||
}
|
||||
dom.replaceWith(container);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue