Add Update Cover from URL command

This commit is contained in:
Evan Fiordeliso 2026-06-10 09:48:43 -04:00
parent 8b19f1ea03
commit 42d42e92c2
2 changed files with 48 additions and 5 deletions

View File

@ -0,0 +1,36 @@
import { type Editor, type MarkdownView, type MarkdownFileInfo, type App, type TFile, Notice } from "obsidian";
import { EditorCheckCommand } from "./Command";
import type { BookTrackerPluginSettings } from "@ui/settings";
export class UpdateCoverFromURLCommand extends EditorCheckCommand {
constructor(
private readonly app: App,
private readonly settings: BookTrackerPluginSettings,
private readonly downloadCoverImage: (url: string, fileName: string, overwrite?: boolean) => Promise<TFile>,
) {
super("update-cover-from-url", "Update Cover from URL");
}
protected check(_editor: Editor, ctx: MarkdownView | MarkdownFileInfo): boolean {
return ctx.file != null;
}
protected async run(_editor: Editor, ctx: MarkdownView | MarkdownFileInfo): Promise<void> {
const file = ctx.file!;
const url = await navigator.clipboard.readText();
let coverFile: TFile;
try {
coverFile = await this.downloadCoverImage(url, file.basename, true);
} catch (error) {
console.error("Failed to download cover image:", error);
new Notice("Failed to download cover image. Check console for details.");
return;
}
this.app.fileManager.processFrontMatter(file, (fm) => {
fm[this.settings.coverImageUrlProperty] = url;
});
new Notice("Updated cover image.")
}
}

View File

@ -35,6 +35,7 @@ import { registerAToZChallengeCodeBlockProcessor } from "@ui/code-blocks/AToZCha
import moment from "@external/moment";
import { compressImage } from "@utils/image";
import { titleSortValue } from "@utils/text";
import { UpdateCoverFromURLCommand } from "@commands/UpdateCoverFromURLCommand";
export default class BookTrackerPlugin extends Plugin {
public settings: BookTrackerPluginSettings;
@ -90,6 +91,7 @@ export default class BookTrackerPlugin extends Plugin {
)
);
this.addCommand(new ReloadReadingLogCommand(this.readingLog));
this.addCommand(new UpdateCoverFromURLCommand(this.app, this.settings, this.downloadCoverImage.bind(this)));
this.addSettingTab(new BookTrackerSettingTab(this));
@ -100,7 +102,7 @@ export default class BookTrackerPlugin extends Plugin {
registerAToZChallengeCodeBlockProcessor(this);
}
onunload() {}
onunload() { }
async loadSettings() {
this.settings = Object.assign(
@ -149,7 +151,12 @@ export default class BookTrackerPlugin extends Plugin {
overwrite?: boolean
): Promise<TFile> {
const response = await requestUrl(coverImageUrl);
const contentType = response.headers["content-type"];
const header = Object.keys(response.headers).find(k => k.toLowerCase() === "content-type") ?? "Content-Type";
const contentType = response.headers[header] ?? "application/octet-stream";
if (!contentType.startsWith("image/") && contentType !== "application/octet-stream") {
throw new Error("Unexpected content type: " + contentType);
}
const urlExtension = coverImageUrl.split(".").pop();
const extension =
@ -217,9 +224,9 @@ export default class BookTrackerPlugin extends Plugin {
})),
series: book.series
? {
...book.series,
title: safeString(book.series.title),
}
...book.series,
title: safeString(book.series.title),
}
: null,
publisher: safeString(book.publisher),
publishedAt: book.publishedAt,