Skip to content

Explanation of the ChatTemplates Class

What is the ChatTemplates class and how does it help users create new chat templates in Obsidian?

The following code block defines a TypeScript class called ChatTemplates that helps users create new chat templates in Obsidian. It extends the built-in SuggestModal class which provides an interface for displaying and selecting suggestions based on user input.

Motivation

To offer insight from an Obsidian plugin developer using the Obsidian API, which is pretty poorly documented/hard to parse.

Constructor Method

The constructor is like the "setup" function when you're building something new. It takes two things: an instance of the main app (App) and some settings for chat templates (ChatGPT_MDSettings). When we create a new instance of this class, we pass these things into it so that it can use them later on.

getFilesInChatFolder Method

This method gets all files from a specific folder path (which is stored as part of our settings). We only want to show chat templates to users, so we filter out any files that aren't in this folder.

getSuggestions Method

When someone types into the search box while using our plugin, this method will be called with whatever they typed as its argument. This method looks at all available chat template files and returns only those whose names match what was typed by the user (case-insensitive).

renderSuggestion Method

Once we have filtered down our list of possible matches based on what was typed by the user, each remaining suggestion needs to be displayed visually somehow. This method creates HTML elements representing each suggestion item one-by-one and adds them to the UI.

bramadams.dev is a reader-supported published Zettelkasten. Both free and paid subscriptions are available. If you want to support my work, the best way is by taking out a paid subscription.

onChooseSuggestion Method

Finally, when someone clicks or selects one of these suggestions from our list, this function will run! First it displays a message saying which template was selected by using Obsidian's built-in Notice API. Then it reads contents from selected template file using Vault API's .read(), creates new markdown file using Vault API's .create(), writes contents read earlier to newly created markdown file and opens newly created markdown note using Workspace API's .openLinkText().

export class ChatTemplates extends SuggestModal<ChatTemplate> {
	settings: ChatGPT_MDSettings;

	constructor(app: App, settings: ChatGPT_MDSettings) {
		super(app);
		this.settings = settings;
	}

	getFilesInChatFolder(): TFile[] {
		return this.app.vault
			.getFiles()
			.filter(
				(file) => file.parent.path === this.settings.chatTemplateFolder
			);
	}

	// Returns all available suggestions.
	getSuggestions(query: string): ChatTemplate[] {
		const chatTemplateFiles = this.getFilesInChatFolder();

		if (query == "") {
			return chatTemplateFiles.map((file) => {
				return {
					title: file.basename,
					file: file,
				};
			});
		}

		return chatTemplateFiles
			.filter((file) => {
				return file.basename.toLowerCase().includes(query.toLowerCase());
			})
			.map((file) => {
				return {
					title: file.basename,
					file: file,
				};
			});
	}

	// Renders each suggestion item.
	renderSuggestion(template: ChatTemplate, el: HTMLElement) {
		el.createEl("div", { text: template.title });
	}

	// Perform action on the selected suggestion.
	async onChooseSuggestion(
		template: ChatTemplate,
		evt: MouseEvent | KeyboardEvent
	) {
		new Notice(`Selected ${template.title}`);
		const templateText = await this.app.vault.read(template.file);
		// use template text to create new file in chat folder
		const file = await this.app.vault.create(
			`${this.settings.chatFolder}/${getDate()}.md`,
			templateText
		);

		// open new file
		this.app.workspace.openLinkText(file.basename, "", true);
	}
}

Comments