@@ -9,6 +9,7 @@ import TodoService, { Todo } from "src/todoService";
99
1010export default class ExtendedTaskListsPlugin extends Plugin {
1111 settings ! : ExtendedTaskListsSettings ;
12+ private isUpdating = false ;
1213
1314 async onload ( ) {
1415 await this . loadSettings ( ) ;
@@ -117,20 +118,83 @@ export default class ExtendedTaskListsPlugin extends Plugin {
117118 }
118119
119120 updateTodoFile = async ( ) => {
121+ if ( this . isUpdating ) return ;
122+ this . isUpdating = true ;
123+ try {
124+ await this . doUpdateTodoFile ( ) ;
125+ } finally {
126+ this . isUpdating = false ;
127+ }
128+ } ;
129+
130+ private async doUpdateTodoFile ( ) {
120131 const vault = this . app . vault ;
121132 const fileService = new VaultFileService ( vault ) ;
122133 const service = new TodoService ( fileService , this . settings ) ;
123- const todoFiles = await service . findTodosFiles ( ) ;
124- const todos : Todo [ ] = todoFiles
134+ const sourceFiles = await service . findTodosFiles ( ) ;
135+ const allTodos : Todo [ ] = sourceFiles
125136 . map ( ( todoFile ) => {
126137 const todos = service . parseTodos ( todoFile . contents ) ;
127138 todos . forEach ( ( todo ) => ( todo . file = todoFile . file ) ) ;
128139 return todos ;
129140 } )
130141 . reduce ( ( prev , cur ) => prev . concat ( cur ) , [ ] ) ;
131- const todoFile = await this . getOrCreateTodoFile ( vault ) ;
132- await service . saveTodos ( todoFile as IFile , todos ) ;
133- } ;
142+
143+ if ( ! this . settings . enableNestedTodos ) {
144+ const todoFile = await this . getOrCreateTodoFile ( vault ) ;
145+ await service . saveTodos ( todoFile as IFile , allTodos ) ;
146+ return ;
147+ }
148+
149+ const allTodoTargets = await service . findAllTodoFiles ( ) ;
150+ const isRootTodoFile = ( f : IFile ) =>
151+ f . path === this . settings . todoFilename ||
152+ f . path === "/" + this . settings . todoFilename ;
153+ const rootTodoFile = allTodoTargets . find ( isRootTodoFile ) ;
154+ const nestedTodoFiles = allTodoTargets . filter (
155+ ( f ) => ! isRootTodoFile ( f ) ,
156+ ) ;
157+
158+ const claimedTodoKeys = new Set < string > ( ) ;
159+
160+ nestedTodoFiles . sort ( ( a , b ) => {
161+ const depthA = a . path . split ( "/" ) . length ;
162+ const depthB = b . path . split ( "/" ) . length ;
163+ return depthB - depthA ;
164+ } ) ;
165+
166+ for ( const nestedTodo of nestedTodoFiles ) {
167+ let scopedTodos = service . filterTodosByScope (
168+ allTodos ,
169+ nestedTodo . path ,
170+ ) ;
171+
172+ if ( this . settings . excludeNestedFromParent ) {
173+ scopedTodos = scopedTodos . filter (
174+ ( todo ) =>
175+ ! claimedTodoKeys . has (
176+ `${ todo . file . path } :${ todo . lineno } ` ,
177+ ) ,
178+ ) ;
179+ for ( const todo of scopedTodos ) {
180+ claimedTodoKeys . add ( `${ todo . file . path } :${ todo . lineno } ` ) ;
181+ }
182+ }
183+
184+ await service . saveTodos ( nestedTodo , scopedTodos ) ;
185+ }
186+
187+ const rootFile =
188+ rootTodoFile ?? ( ( await this . getOrCreateTodoFile ( vault ) ) as IFile ) ;
189+ let rootTodos = allTodos ;
190+ if ( this . settings . excludeNestedFromParent && claimedTodoKeys . size > 0 ) {
191+ rootTodos = allTodos . filter (
192+ ( todo ) =>
193+ ! claimedTodoKeys . has ( `${ todo . file . path } :${ todo . lineno } ` ) ,
194+ ) ;
195+ }
196+ await service . saveTodos ( rootFile , rootTodos ) ;
197+ }
134198
135199 onTodoFileUpdated = async ( todoFile : TFile ) : Promise < boolean > => {
136200 const vault = this . app . vault ;
0 commit comments