mirror of
https://github.com/ebullient/obsidian-deck-notes.git
synced 2026-07-22 06:40:43 +00:00
🎨 ✨ Add API to embed card content in notes (as callout).
Move callout type to setting. Defer registration of API and commands until cards have been read.
This commit is contained in:
parent
1f90617591
commit
a3087ac729
7 changed files with 124 additions and 49 deletions
1
src/@types/settings.d.ts
vendored
1
src/@types/settings.d.ts
vendored
|
|
@ -10,6 +10,7 @@ export interface SimpleFlashcardsSettings {
|
|||
defaultDeckPath: string; // Default path for quick command
|
||||
trackViews: boolean; // Enable view tracking
|
||||
selectionMode: "random" | "least-recent";
|
||||
calloutType: string; // Callout type for embedded cards (e.g., "readaloud")
|
||||
}
|
||||
|
||||
export interface SimpleFlashcardsData {
|
||||
|
|
|
|||
9
src/@types/window-type.d.ts
vendored
Normal file
9
src/@types/window-type.d.ts
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import type { SimpleFlashcardsApi } from "../flashcards-Api";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
simpleFlashcards?: {
|
||||
api?: SimpleFlashcardsApi;
|
||||
};
|
||||
}
|
||||
}
|
||||
17
src/flashcards-Api.ts
Normal file
17
src/flashcards-Api.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import type SimpleFlashcardsPlugin from "./flashcards-Plugin";
|
||||
|
||||
export class SimpleFlashcardsApi {
|
||||
plugin: SimpleFlashcardsPlugin;
|
||||
|
||||
constructor(plugin: SimpleFlashcardsPlugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random card embed as formatted text
|
||||
* @returns The card embed text, or null if no cards available
|
||||
*/
|
||||
embedCard(): string | null {
|
||||
return this.plugin.getCardEmbedText();
|
||||
}
|
||||
}
|
||||
|
|
@ -5,4 +5,5 @@ export const DEFAULT_SETTINGS: SimpleFlashcardsSettings = {
|
|||
defaultDeckPath: "",
|
||||
trackViews: true,
|
||||
selectionMode: "least-recent",
|
||||
calloutType: "tip",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { Notice, Plugin, TFile, TFolder } from "obsidian";
|
||||
import { type Editor, Notice, Plugin, TFile, TFolder } from "obsidian";
|
||||
import type {
|
||||
Card,
|
||||
SimpleFlashcardsData,
|
||||
SimpleFlashcardsSettings,
|
||||
} from "./@types/settings";
|
||||
import { SimpleFlashcardsApi } from "./flashcards-Api";
|
||||
import { CardParser } from "./flashcards-CardParser";
|
||||
import { DEFAULT_SETTINGS } from "./flashcards-Constants";
|
||||
import { FlashcardModal } from "./flashcards-Modal";
|
||||
|
|
@ -14,6 +15,7 @@ export default class SimpleFlashcardsPlugin extends Plugin {
|
|||
data!: SimpleFlashcardsData;
|
||||
cachedCards: Card[] = [];
|
||||
cardParser!: CardParser;
|
||||
api!: SimpleFlashcardsApi;
|
||||
|
||||
async onload() {
|
||||
console.log("Loading Simple Flashcards plugin");
|
||||
|
|
@ -23,33 +25,54 @@ export default class SimpleFlashcardsPlugin extends Plugin {
|
|||
|
||||
this.addSettingTab(new SimpleFlashcardsSettingsTab(this.app, this));
|
||||
|
||||
// Command: Show Random Activity Card
|
||||
this.addCommand({
|
||||
id: "show-random-card",
|
||||
name: "Show Random Activity Card",
|
||||
callback: () => {
|
||||
this.showRandomCard();
|
||||
},
|
||||
});
|
||||
|
||||
// Command: Refresh Activity Cards
|
||||
this.addCommand({
|
||||
id: "refresh-cards",
|
||||
name: "Refresh Activity Cards",
|
||||
callback: async () => {
|
||||
await this.scanCards();
|
||||
new Notice("Activity cards refreshed");
|
||||
},
|
||||
});
|
||||
|
||||
// Defer initial card scan to avoid blocking startup
|
||||
// Defer initial card scan, API, and command registration to avoid blocking startup
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
await this.scanCards();
|
||||
|
||||
// Initialize API
|
||||
this.api = new SimpleFlashcardsApi(this);
|
||||
if (!window.simpleFlashcards) {
|
||||
window.simpleFlashcards = {};
|
||||
}
|
||||
window.simpleFlashcards.api = this.api;
|
||||
|
||||
// Command: Show Random Activity Card
|
||||
this.addCommand({
|
||||
id: "show-random-card",
|
||||
name: "Show Activity Card",
|
||||
callback: () => {
|
||||
this.showRandomCard();
|
||||
},
|
||||
});
|
||||
|
||||
// Command: Embed Random Card
|
||||
this.addCommand({
|
||||
id: "embed-card",
|
||||
name: "Embed Activity Card",
|
||||
editorCallback: (editor) => {
|
||||
this.insertCardEmbed(editor);
|
||||
},
|
||||
});
|
||||
|
||||
// Command: Refresh Activity Cards
|
||||
this.addCommand({
|
||||
id: "refresh-cards",
|
||||
name: "Refresh Activity Cards",
|
||||
callback: async () => {
|
||||
await this.scanCards();
|
||||
new Notice("Activity cards refreshed");
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onunload() {
|
||||
console.log("Unloading Simple Flashcards plugin");
|
||||
|
||||
// Clear API reference
|
||||
if (window.simpleFlashcards) {
|
||||
window.simpleFlashcards.api = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
|
|
@ -129,12 +152,7 @@ export default class SimpleFlashcardsPlugin extends Plugin {
|
|||
});
|
||||
}
|
||||
|
||||
async showRandomCard() {
|
||||
// Lazy load cards if not yet scanned
|
||||
if (this.cachedCards.length === 0) {
|
||||
await this.scanCards();
|
||||
}
|
||||
|
||||
showRandomCard() {
|
||||
const deckPath = this.settings.defaultDeckPath || undefined;
|
||||
const card = this.selectCard(deckPath);
|
||||
|
||||
|
|
@ -145,4 +163,41 @@ export default class SimpleFlashcardsPlugin extends Plugin {
|
|||
|
||||
new FlashcardModal(this.app, this, card, deckPath).open();
|
||||
}
|
||||
|
||||
getCardEmbedText(): string | null {
|
||||
const deckPath = this.settings.defaultDeckPath || undefined;
|
||||
const card = this.selectCard(deckPath);
|
||||
|
||||
if (!card) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create collapsible callout with card content
|
||||
const contentLines = card.content
|
||||
.split("\n")
|
||||
.map((line) => `> ${line}`);
|
||||
|
||||
const embedText = [
|
||||
`> [!${this.settings.calloutType}]+ ${card.heading}`,
|
||||
...contentLines,
|
||||
].join("\n");
|
||||
|
||||
// Record as viewed
|
||||
if (this.settings.trackViews) {
|
||||
this.recordView(card.key);
|
||||
}
|
||||
|
||||
return embedText;
|
||||
}
|
||||
|
||||
insertCardEmbed(editor: Editor) {
|
||||
const embedText = this.getCardEmbedText();
|
||||
|
||||
if (!embedText) {
|
||||
new Notice("No cards available. Check your settings.");
|
||||
return;
|
||||
}
|
||||
|
||||
editor.replaceSelection(embedText);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,6 +124,20 @@ export class SimpleFlashcardsSettingsTab extends PluginSettingTab {
|
|||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Callout Type")
|
||||
.setDesc(
|
||||
"Callout type for embedded cards (e.g., note, tip, warning)",
|
||||
)
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder("readaloud")
|
||||
.setValue(this.newSettings.calloutType)
|
||||
.onChange((value) => {
|
||||
this.newSettings.calloutType = value.trim();
|
||||
}),
|
||||
);
|
||||
|
||||
containerEl.createEl("h3", { text: "Usage" });
|
||||
const usage = containerEl.createEl("div");
|
||||
usage.createEl("p", {
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES2020",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES2020"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue