1- import { AbstractInputSuggest , App , Notice , PluginSettingTab , Setting , TextComponent , TFolder , normalizePath } from "obsidian" ;
1+ import { AbstractInputSuggest , App , Notice , PluginSettingTab , Setting , TextComponent , TFile , TFolder , normalizePath } from "obsidian" ;
22import type ParaManagerPlugin from "./main" ;
33import { validateParaFolderPath , type ParaFolderField } from "./utils" ;
4+ import { ensureFolderExists } from "./folder-ops" ;
5+ import type { FileExplorerView } from "./obsidian-internals" ;
46
5- /**
6- * Ensure a folder exists in the vault, creating it if necessary.
7- */
8- async function ensureFolderExistsVault ( app : App , folderPath : string ) : Promise < void > {
9- const normalized = normalizePath ( folderPath ) ;
10- const existing = app . vault . getAbstractFileByPath ( normalized ) ;
11- if ( ! existing ) {
12- await app . vault . createFolder ( normalized ) ;
13- }
14- }
7+ /** Default folder for storing templates */
8+ const DEFAULT_TEMPLATES_FOLDER = "Templates" ;
159
1610/**
1711 * Generate a default template for a PARA item type.
@@ -63,6 +57,44 @@ A resource is a topic or tool you want to reference in the future.
6357 return descriptions [ itemType ] || `# {{name}}\n` ;
6458}
6559
60+ /**
61+ * Handle the "Generate Default" button click for template settings.
62+ * Creates a default template file, updates the corresponding setting, and refreshes the UI.
63+ *
64+ * @param plugin - The ParaManagerPlugin instance
65+ * @param itemType - The PARA item type (Project, Area, or Resource)
66+ * @param settingsKey - The settings key to update (projectTemplatePath, areaTemplatePath, or resourceTemplatePath)
67+ * @param refreshDisplay - Function to refresh the settings display UI
68+ */
69+ async function generateDefaultTemplateHandler (
70+ plugin : ParaManagerPlugin ,
71+ itemType : "Project" | "Area" | "Resource" ,
72+ settingsKey : "projectTemplatePath" | "areaTemplatePath" | "resourceTemplatePath" ,
73+ refreshDisplay : ( ) => void
74+ ) : Promise < void > {
75+ const defaultContent = generateDefaultTemplate ( itemType ) ;
76+ await ensureFolderExists ( plugin . app , DEFAULT_TEMPLATES_FOLDER ) ;
77+ const templatePath = `${ DEFAULT_TEMPLATES_FOLDER } /${ itemType } .md` ;
78+
79+ // Check if template already exists
80+ const existing = plugin . app . vault . getAbstractFileByPath ( templatePath ) ;
81+ if ( existing ) {
82+ new Notice ( "Template already exists at " + templatePath ) ;
83+ return ;
84+ }
85+
86+ try {
87+ await plugin . app . vault . create ( templatePath , defaultContent ) ;
88+ plugin . settings [ settingsKey ] = templatePath ;
89+ await plugin . saveSettings ( ) ;
90+ refreshDisplay ( ) ; // Refresh UI
91+ new Notice ( `Created ${ itemType . toLowerCase ( ) } template at ${ templatePath } ` ) ;
92+ } catch ( error ) {
93+ const message = error instanceof Error ? error . message : "Unknown error" ;
94+ new Notice ( "Failed to create template: " + message ) ;
95+ }
96+ }
97+
6698/**
6799 * Provides folder autocomplete suggestions for text inputs.
68100 * Uses Obsidian's AbstractInputSuggest to show a dropdown of matching folders.
@@ -148,15 +180,15 @@ function setupTemplatePathInput(
148180 const inputEl = text . inputEl ;
149181
150182 // Create a custom suggest for markdown files
151- class FileInputSuggest extends AbstractInputSuggest < any > {
183+ class FileInputSuggest extends AbstractInputSuggest < TFile > {
152184 constructor ( app : App , inputEl : HTMLInputElement ) {
153185 super ( app , inputEl ) ;
154186 }
155187
156- getSuggestions ( inputStr : string ) : any [ ] {
188+ getSuggestions ( inputStr : string ) : TFile [ ] {
157189 const files = plugin . app . vault . getAllLoadedFiles ( )
158- . filter ( ( f ) : f is any => {
159- return typeof f . name === "string" && f . name . endsWith ( ".md" ) ;
190+ . filter ( ( f ) : f is TFile => {
191+ return f instanceof TFile && f . name . endsWith ( ".md" ) ;
160192 } ) ;
161193
162194 if ( ! inputStr ) return files . slice ( 0 , 50 ) ; // Limit suggestions
@@ -167,11 +199,11 @@ function setupTemplatePathInput(
167199 ) . slice ( 0 , 20 ) ;
168200 }
169201
170- renderSuggestion ( file : any , el : HTMLElement ) : void {
202+ renderSuggestion ( file : TFile , el : HTMLElement ) : void {
171203 el . setText ( file . path ) ;
172204 }
173205
174- selectSuggestion ( file : any ) : void {
206+ selectSuggestion ( file : TFile ) : void {
175207 this . setValue ( file . path ) ;
176208 this . close ( ) ;
177209 }
@@ -449,7 +481,7 @@ export class ParaManagerSettingTab extends PluginSettingTab {
449481 this . plugin . installSortingPatch ( ) ;
450482 const fileExplorer = this . plugin . app . workspace . getLeavesOfType ( "file-explorer" ) [ 0 ] ;
451483 if ( fileExplorer ) {
452- ( fileExplorer . view as any ) . requestSort ?.( ) ;
484+ ( fileExplorer . view as FileExplorerView ) . requestSort ?.( ) ;
453485 }
454486 } )
455487 ) ;
@@ -479,28 +511,12 @@ export class ParaManagerSettingTab extends PluginSettingTab {
479511 button
480512 . setButtonText ( "Generate Default" )
481513 . onClick ( async ( ) => {
482- const defaultContent = generateDefaultTemplate ( "Project" ) ;
483- const templatesFolder = "Templates" ;
484- await ensureFolderExistsVault ( this . plugin . app , templatesFolder ) ;
485- const templatePath = `${ templatesFolder } /Project.md` ;
486-
487- // Check if template already exists
488- const existing = this . plugin . app . vault . getAbstractFileByPath ( templatePath ) ;
489- if ( existing ) {
490- new Notice ( "Template already exists at " + templatePath ) ;
491- return ;
492- }
493-
494- try {
495- await this . plugin . app . vault . create ( templatePath , defaultContent ) ;
496- this . plugin . settings . projectTemplatePath = templatePath ;
497- await this . plugin . saveSettings ( ) ;
498- this . display ( ) ; // Refresh UI
499- new Notice ( "Created project template at " + templatePath ) ;
500- } catch ( error ) {
501- const message = error instanceof Error ? error . message : "Unknown error" ;
502- new Notice ( "Failed to create template: " + message ) ;
503- }
514+ await generateDefaultTemplateHandler (
515+ this . plugin ,
516+ "Project" ,
517+ "projectTemplatePath" ,
518+ ( ) => this . display ( )
519+ ) ;
504520 } )
505521 ) ;
506522
@@ -526,28 +542,12 @@ export class ParaManagerSettingTab extends PluginSettingTab {
526542 button
527543 . setButtonText ( "Generate Default" )
528544 . onClick ( async ( ) => {
529- const defaultContent = generateDefaultTemplate ( "Area" ) ;
530- const templatesFolder = "Templates" ;
531- await ensureFolderExistsVault ( this . plugin . app , templatesFolder ) ;
532- const templatePath = `${ templatesFolder } /Area.md` ;
533-
534- // Check if template already exists
535- const existing = this . plugin . app . vault . getAbstractFileByPath ( templatePath ) ;
536- if ( existing ) {
537- new Notice ( "Template already exists at " + templatePath ) ;
538- return ;
539- }
540-
541- try {
542- await this . plugin . app . vault . create ( templatePath , defaultContent ) ;
543- this . plugin . settings . areaTemplatePath = templatePath ;
544- await this . plugin . saveSettings ( ) ;
545- this . display ( ) ; // Refresh UI
546- new Notice ( "Created area template at " + templatePath ) ;
547- } catch ( error ) {
548- const message = error instanceof Error ? error . message : "Unknown error" ;
549- new Notice ( "Failed to create template: " + message ) ;
550- }
545+ await generateDefaultTemplateHandler (
546+ this . plugin ,
547+ "Area" ,
548+ "areaTemplatePath" ,
549+ ( ) => this . display ( )
550+ ) ;
551551 } )
552552 ) ;
553553
@@ -573,28 +573,12 @@ export class ParaManagerSettingTab extends PluginSettingTab {
573573 button
574574 . setButtonText ( "Generate Default" )
575575 . onClick ( async ( ) => {
576- const defaultContent = generateDefaultTemplate ( "Resource" ) ;
577- const templatesFolder = "Templates" ;
578- await ensureFolderExistsVault ( this . plugin . app , templatesFolder ) ;
579- const templatePath = `${ templatesFolder } /Resource.md` ;
580-
581- // Check if template already exists
582- const existing = this . plugin . app . vault . getAbstractFileByPath ( templatePath ) ;
583- if ( existing ) {
584- new Notice ( "Template already exists at " + templatePath ) ;
585- return ;
586- }
587-
588- try {
589- await this . plugin . app . vault . create ( templatePath , defaultContent ) ;
590- this . plugin . settings . resourceTemplatePath = templatePath ;
591- await this . plugin . saveSettings ( ) ;
592- this . display ( ) ; // Refresh UI
593- new Notice ( "Created resource template at " + templatePath ) ;
594- } catch ( error ) {
595- const message = error instanceof Error ? error . message : "Unknown error" ;
596- new Notice ( "Failed to create template: " + message ) ;
597- }
576+ await generateDefaultTemplateHandler (
577+ this . plugin ,
578+ "Resource" ,
579+ "resourceTemplatePath" ,
580+ ( ) => this . display ( )
581+ ) ;
598582 } )
599583 ) ;
600584 }
0 commit comments