mirror of
https://github.com/benstuart0/on-this-day-i-obsidian.git
synced 2026-07-22 05:38:19 +00:00
Respond to joethei MR comments. Minor changes, use addNumberFormat, use AbstractInputSuggest.
This commit is contained in:
parent
880b1eb3db
commit
0c075ff854
5 changed files with 170 additions and 69 deletions
92
main.ts
92
main.ts
|
|
@ -1,4 +1,4 @@
|
|||
import { MarkdownView, Notice, Plugin, TFolder } from "obsidian";
|
||||
import { MarkdownView, Notice, Plugin, TFolder, Editor } from "obsidian";
|
||||
import OpenAI from "openai";
|
||||
import { OnThisDayPluginSettings, DEFAULT_SETTINGS } from "src/settings";
|
||||
import OnThisDaySettingTab from "src/OnThisDaySettingTab";
|
||||
|
|
@ -17,35 +17,93 @@ export default class OnThisDayPlugin extends Plugin {
|
|||
await this.loadSettings();
|
||||
this.addSettingTab(new OnThisDaySettingTab(this.app, this));
|
||||
|
||||
// Conditions: placeholder must be defined in settings
|
||||
this.addCommand({
|
||||
id: "through-the-years-placeholder",
|
||||
name: "Add Through The Years Placeholder at Cursor",
|
||||
callback: () => {
|
||||
this.addThroughTheYearsPlaceholder();
|
||||
name: "Add through the years placeholder at cursor",
|
||||
editorCheckCallback: (
|
||||
checking: boolean,
|
||||
editor: Editor,
|
||||
view: MarkdownView
|
||||
) => {
|
||||
const placeholderIsEmpty =
|
||||
this.settings.placeholder.trim() === "";
|
||||
if (!placeholderIsEmpty) {
|
||||
if (!checking) {
|
||||
this.addThroughTheYearsPlaceholder();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
// Conditions: placeholder must be defined in settings
|
||||
this.addCommand({
|
||||
id: "diet-estimates-placeholder",
|
||||
name: "Add Diet Estimates Placeholder at Cursor",
|
||||
callback: () => {
|
||||
this.addDietEstimatesPlaceholder();
|
||||
name: "Add diet estimates placeholder at cursor",
|
||||
editorCheckCallback: (
|
||||
checking: boolean,
|
||||
editor: Editor,
|
||||
view: MarkdownView
|
||||
) => {
|
||||
const placeholderIsEmpty =
|
||||
this.settings.dietEstimatePlaceholder.trim() === "";
|
||||
if (!placeholderIsEmpty) {
|
||||
if (!checking) {
|
||||
this.addDietEstimatesPlaceholder();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
// Conditions: date format, daily notes folder, output header, model version, and apiKey
|
||||
this.addCommand({
|
||||
id: "generate-date-summaries",
|
||||
name: "Generate Through The Years",
|
||||
callback: async () => {
|
||||
await this.generateDateSummaries();
|
||||
name: "Generate through The years",
|
||||
editorCheckCallback: (
|
||||
checking: boolean,
|
||||
editor: Editor,
|
||||
view: MarkdownView
|
||||
) => {
|
||||
if (
|
||||
this.settings.dateFormat.trim() != "" &&
|
||||
this.settings.dailyNotesFolder.trim() != "" &&
|
||||
this.settings.throughTheYearsHeader.trim() != "" &&
|
||||
this.settings.model.trim() != "" &&
|
||||
this.settings.openaiApiKey.trim() != ""
|
||||
) {
|
||||
if (!checking) {
|
||||
this.generateDateSummaries();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
// Conditions: section header, model version, and apiKey
|
||||
this.addCommand({
|
||||
id: "diet-estimates",
|
||||
name: "Generate Diet Estimates",
|
||||
callback: async () => {
|
||||
await this.generateDietEstimates();
|
||||
name: "Generate diet estimates",
|
||||
editorCheckCallback: (
|
||||
checking: boolean,
|
||||
editor: Editor,
|
||||
view: MarkdownView
|
||||
) => {
|
||||
if (
|
||||
this.settings.foodHeader.trim() != "" &&
|
||||
this.settings.model.trim() != "" &&
|
||||
this.settings.openaiApiKey.trim() != ""
|
||||
) {
|
||||
if (!checking) {
|
||||
this.generateDateSummaries();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -202,7 +260,10 @@ export default class OnThisDayPlugin extends Plugin {
|
|||
);
|
||||
|
||||
if (headerIndex === -1) {
|
||||
new Notice("Food section not found using header: " + this.settings.foodHeader);
|
||||
new Notice(
|
||||
"Food section not found using header: " +
|
||||
this.settings.foodHeader
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +280,8 @@ export default class OnThisDayPlugin extends Plugin {
|
|||
|
||||
if (!foodInfo) {
|
||||
new Notice(
|
||||
"No food-related details found under the header: " + this.settings.foodHeader
|
||||
"No food-related details found under the header: " +
|
||||
this.settings.foodHeader
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
10
package-lock.json
generated
10
package-lock.json
generated
|
|
@ -1974,16 +1974,6 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.29.4",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
|
|
|
|||
47
src/FolderSuggest.ts
Normal file
47
src/FolderSuggest.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import { App, AbstractInputSuggest } from "obsidian";
|
||||
|
||||
export class FolderSuggest extends AbstractInputSuggest<string> {
|
||||
private folderOptions: string[];
|
||||
|
||||
/**
|
||||
* Constructs a new FolderSuggest.
|
||||
* @param app - The Obsidian App instance.
|
||||
* @param textInputEl - The HTMLInputElement (or contentEditable div) to attach the suggestion to.
|
||||
* @param folderOptions - An array of folder path strings to suggest.
|
||||
*/
|
||||
constructor(
|
||||
app: App,
|
||||
textInputEl: HTMLInputElement,
|
||||
folderOptions: string[]
|
||||
) {
|
||||
super(app, textInputEl);
|
||||
this.folderOptions = folderOptions;
|
||||
this.limit = 20;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of folder paths that match the given query.
|
||||
*/
|
||||
protected getSuggestions(query: string): string[] {
|
||||
return this.folderOptions.filter((option) =>
|
||||
option.toLowerCase().includes(query.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a suggestion item in the suggestion dropdown.
|
||||
* @param suggestion - The folder path suggestion.
|
||||
* @param el - The HTMLElement in which to render the suggestion.
|
||||
*/
|
||||
renderSuggestion(suggestion: string, el: HTMLElement): void {
|
||||
el.textContent = suggestion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user selects a suggestion.
|
||||
* Updates the input field with the chosen folder path.
|
||||
*/
|
||||
onChooseSuggestion(suggestion: string): void {
|
||||
this.setValue(suggestion);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { App, PluginSettingTab, Setting, TFolder } from "obsidian";
|
||||
import moment from "moment";
|
||||
import { App, PluginSettingTab, Setting, TFolder, moment } from "obsidian";
|
||||
import OnThisDayPlugin from "main";
|
||||
import { FolderSuggest } from "./FolderSuggest";
|
||||
|
||||
export default class OnThisDaySettingTab extends PluginSettingTab {
|
||||
plugin: OnThisDayPlugin;
|
||||
|
|
@ -13,23 +13,22 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
containerEl.createEl("h2", { text: "General Settings" });
|
||||
|
||||
const dateSetting = new Setting(containerEl)
|
||||
.setName("Date Format")
|
||||
.setName("Date format")
|
||||
.setDesc(
|
||||
`Format for daily note filenames. Example: ${moment(
|
||||
new Date()
|
||||
).format(this.plugin.settings.dateFormat)}`
|
||||
)
|
||||
.addText((text) => {
|
||||
text.setPlaceholder("MMMM D, YYYY")
|
||||
.addMomentFormat((momentFormat) => {
|
||||
momentFormat
|
||||
.setDefaultFormat("MMMM D, YYYY")
|
||||
.setValue(this.plugin.settings.dateFormat)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.dateFormat = value;
|
||||
await this.plugin.saveSettings();
|
||||
// Update the description with a new example using the updated format
|
||||
const newExample = moment(new Date()).format(value);
|
||||
// Update the description with a new example using the updated format
|
||||
dateSetting.setDesc(
|
||||
`Format for daily note filenames. Example: ${newExample}`
|
||||
);
|
||||
|
|
@ -37,33 +36,37 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Daily Notes Folder")
|
||||
.setName("Daily notes folder")
|
||||
.setDesc("Select the folder where your daily notes are stored.")
|
||||
.addDropdown((dropdown) => {
|
||||
// Create an object to hold the folder options
|
||||
const folderOptions: Record<string, string> = {};
|
||||
// Get all files from the vault and filter for folders
|
||||
const allFolders = this.app.vault
|
||||
.addText((textComponent) => {
|
||||
textComponent.setValue(
|
||||
this.plugin.settings.dailyNotesFolder || ""
|
||||
);
|
||||
// Set a placeholder to prompt the user.
|
||||
textComponent.setPlaceholder("Search for folder...");
|
||||
// Retrieve folder options by filtering all loaded files for TFolder instances.
|
||||
const folderOptions: string[] = this.app.vault
|
||||
.getAllLoadedFiles()
|
||||
.filter((f): f is TFolder => f instanceof TFolder);
|
||||
// Populate the folderOptions with folder paths
|
||||
allFolders.forEach((folder) => {
|
||||
folderOptions[folder.path] = folder.path;
|
||||
});
|
||||
// Add each folder option to the dropdown
|
||||
for (const key in folderOptions) {
|
||||
dropdown.addOption(key, folderOptions[key]);
|
||||
}
|
||||
// Set the current value from the plugin settings
|
||||
dropdown.setValue(this.plugin.settings.dailyNotesFolder);
|
||||
dropdown.onChange(async (value: string) => {
|
||||
this.plugin.settings.dailyNotesFolder = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
.filter((f): f is TFolder => f instanceof TFolder)
|
||||
.map((folder) => folder.path);
|
||||
const folderSuggest = new FolderSuggest(
|
||||
this.app,
|
||||
textComponent.inputEl,
|
||||
folderOptions
|
||||
);
|
||||
// Save to settings and update text when a suggestion is chosen
|
||||
folderSuggest.onSelect(
|
||||
(suggestion: string, evt: MouseEvent | KeyboardEvent) => {
|
||||
textComponent.setValue(suggestion);
|
||||
this.plugin.settings.dailyNotesFolder = suggestion;
|
||||
this.plugin.saveSettings();
|
||||
folderSuggest.close();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Horizontal Lines")
|
||||
.setName("Horizontal lines")
|
||||
.setDesc(
|
||||
"Would you like horizontal lines above or below the output block?"
|
||||
)
|
||||
|
|
@ -80,7 +83,7 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Custom Prompt Details")
|
||||
.setName("Custom prompt details")
|
||||
.setDesc(
|
||||
"Add custom details to the prompt if you prefer. E.g., Please prioritize things I accomplished or only tell me positive things."
|
||||
)
|
||||
|
|
@ -96,7 +99,7 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Placeholder Tag")
|
||||
.setName("Placeholder tag")
|
||||
.setDesc(
|
||||
"The plugin will search for this text in your active file to replace with its return block. Otherwise outputs at cursor. Default <!OTDI>"
|
||||
)
|
||||
|
|
@ -110,13 +113,12 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Through the Years Output Header")
|
||||
.setName("Through the years output header")
|
||||
.setDesc(
|
||||
"How do you want to title the output block of the Through the Years command? The default is `On This Day`"
|
||||
)
|
||||
.addText((text) =>
|
||||
text
|
||||
.setValue("On This Day")
|
||||
.setValue(
|
||||
this.plugin.settings.throughTheYearsHeader ||
|
||||
"On This Day"
|
||||
|
|
@ -142,7 +144,7 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Output Length (Sentences)")
|
||||
.setName("Output length (sentences)")
|
||||
.setDesc(
|
||||
"Select how many sentences should each year's response be (between 1 and 8)."
|
||||
)
|
||||
|
|
@ -161,10 +163,10 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
containerEl.createEl("h2", { text: "OpenAI Settings" });
|
||||
|
||||
new Setting(containerEl).setName("OpenAI").setHeading();
|
||||
new Setting(containerEl)
|
||||
.setName("Model Version")
|
||||
.setName("Model sersion")
|
||||
.setDesc("Select the OpenAI model to use.")
|
||||
.addDropdown((dropdown) => {
|
||||
dropdown.addOption("gpt-3.5-turbo", "gpt-3.5-turbo");
|
||||
|
|
@ -177,8 +179,8 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("OpenAI API Key")
|
||||
.setDesc("Your OpenAI API key.")
|
||||
.setName("OpenAI api key")
|
||||
.setDesc("Your OpenAI api key.")
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder("sk-...")
|
||||
|
|
@ -189,9 +191,9 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
})
|
||||
);
|
||||
|
||||
containerEl.createEl("h2", { text: "Health Estimate Settings" });
|
||||
new Setting(containerEl).setName("Health estimates").setHeading();
|
||||
new Setting(containerEl)
|
||||
.setName("Health Estimates Placeholder Tag")
|
||||
.setName("Health estimates placeholder tag")
|
||||
.setDesc(
|
||||
"The plugin will search for this text in your active file to replace with its return block. Otherwise outputs at cursor. Default <!OTDI diet>"
|
||||
)
|
||||
|
|
@ -209,7 +211,7 @@ export default class OnThisDaySettingTab extends PluginSettingTab {
|
|||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Food Section Header")
|
||||
.setName("Food section header")
|
||||
.setDesc(
|
||||
"Enter the header that marks the food section in your daily note. Default is '### Food'."
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import moment from "moment";
|
||||
import { moment } from "obsidian";
|
||||
|
||||
//
|
||||
// Utility Functions
|
||||
|
|
|
|||
Loading…
Reference in a new issue