@@ -8,19 +8,12 @@ import {
88} from "@codemirror/view" ;
99import { EditorState , Range , StateField } from "@codemirror/state" ;
1010import { TFile , App , MetadataCache , editorInfoField } from "obsidian" ;
11- import { foldable , syntaxTree , tokenClassNodeProp } from "@codemirror/language" ;
12- import { RegExpCursor } from "./regexp-cursor" ;
1311import { TaskTimerSettings } from "../common/setting-definition" ;
1412import { TaskTimerMetadataDetector } from "../utils/TaskTimerMetadataDetector" ;
1513import { TaskTimerManager , TimerState } from "../utils/TaskTimerManager" ;
1614import { TaskTimerFormatter } from "../utils/TaskTimerFormatter" ;
1715import "../styles/task-timer.css" ;
1816
19- interface TextRange {
20- from : number ;
21- to : number ;
22- }
23-
2417// Extension configuration for StateField access
2518interface TaskTimerConfig {
2619 settings : TaskTimerSettings ;
@@ -418,39 +411,40 @@ function createTaskTimerDecorations(state: EditorState): DecorationSet {
418411 if ( isTaskLine ( lineText ) ) {
419412 console . log ( "[TaskTimer] Found task line:" , lineText . trim ( ) ) ;
420413
421- // Use existing folding logic to check if this is a parent task
422- const range = calculateRangeForTransform ( state , {
423- from : line . from ,
424- to : line . to ,
425- } ) ;
426-
427- if (
428- range &&
429- range . to > line . to &&
430- hasSubTasks ( doc . sliceString ( range . from , range . to ) , lineText )
431- ) {
432- console . log ( "[TaskTimer] Found parent task with subtasks" ) ;
433- // Extract existing block reference if present
434- const existingBlockId = extractBlockRef ( lineText ) ;
414+ // Check if next line exists and has greater indentation (simple check)
415+ if ( i < doc . lines ) {
416+ const nextLine = doc . line ( i + 1 ) ;
417+ const nextLineText = nextLine . text ;
435418
436- // Create block-level timer widget decoration
437- const timerDeco = Decoration . widget ( {
438- widget : new TaskTimerWidget (
439- state ,
440- timerConfig . settings ,
441- timerManager ,
442- line . from ,
443- line . to ,
444- file . path ,
445- existingBlockId
446- ) ,
447- side : - 1 ,
448- block : true // This is now allowed in StateField
449- } ) ;
419+ // Simple indentation check
420+ const currentIndent = lineText . match ( / ^ ( \s * ) / ) ?. [ 1 ] . length || 0 ;
421+ const nextIndent = nextLineText . match ( / ^ ( \s * ) / ) ?. [ 1 ] . length || 0 ;
450422
451- // Add decoration at the start of the line
452- decorations . push ( timerDeco . range ( line . from ) ) ;
453- console . log ( "[TaskTimer] Added timer decoration for line:" , i ) ;
423+ // If next line has more indentation, this is a parent task
424+ if ( nextIndent > currentIndent && nextLineText . trim ( ) ) {
425+ console . log ( "[TaskTimer] Found parent task with subtasks (next line indent:" , nextIndent , "vs" , currentIndent , ")" ) ;
426+ // Extract existing block reference if present
427+ const existingBlockId = extractBlockRef ( lineText ) ;
428+
429+ // Create block-level timer widget decoration
430+ const timerDeco = Decoration . widget ( {
431+ widget : new TaskTimerWidget (
432+ state ,
433+ timerConfig . settings ,
434+ timerManager ,
435+ line . from ,
436+ line . to ,
437+ file . path ,
438+ existingBlockId
439+ ) ,
440+ side : - 1 ,
441+ block : true // This is now allowed in StateField
442+ } ) ;
443+
444+ // Add decoration at the start of the line
445+ decorations . push ( timerDeco . range ( line . from ) ) ;
446+ console . log ( "[TaskTimer] Added timer decoration for line:" , i ) ;
447+ }
454448 }
455449 }
456450 }
@@ -466,72 +460,12 @@ function isTaskLine(lineText: string): boolean {
466460 return / ^ \s * [ - * + ] \s + \[ [ x X ] \] / . test ( lineText ) ;
467461}
468462
469- function hasSubTasks ( rangeText : string , parentLineText : string ) : boolean {
470- const lines = rangeText . split ( "\n" ) ;
471- if ( lines . length <= 1 ) return false ;
472-
473- // Get parent indentation level
474- const parentMatch = parentLineText . match ( / ^ ( \s * ) / ) ;
475- const parentIndent = parentMatch ? parentMatch [ 1 ] . length : 0 ;
476-
477- console . log ( `[TaskTimer] Checking subtasks for parent with indent ${ parentIndent } ` ) ;
478-
479- // Check subsequent lines for subtasks
480- let foundSubtask = false ;
481- for ( let i = 1 ; i < lines . length ; i ++ ) {
482- const line = lines [ i ] ;
483-
484- // Skip empty lines
485- if ( ! line . trim ( ) ) continue ;
486-
487- const lineMatch = line . match ( / ^ ( \s * ) / ) ;
488- const lineIndent = lineMatch ? lineMatch [ 1 ] . length : 0 ;
489-
490- // If we find a line with same or less indentation that's not empty, stop checking
491- if ( lineIndent <= parentIndent ) {
492- break ;
493- }
494-
495- // Check if this indented line is a task
496- if ( isTaskLine ( line ) && lineIndent > parentIndent ) {
497- console . log ( `[TaskTimer] Found subtask: ${ line . trim ( ) } ` ) ;
498- foundSubtask = true ;
499- break ;
500- }
501- }
502-
503- return foundSubtask ;
504- }
505463
506464function extractBlockRef ( lineText : string ) : string | undefined {
507465 const match = lineText . match ( / \^ ( [ a - z A - Z 0 - 9 \- _ ] + ) \s * $ / ) ;
508466 return match ? match [ 1 ] : undefined ;
509467}
510468
511- function calculateRangeForTransform (
512- state : EditorState ,
513- range : TextRange
514- ) : TextRange | null {
515- const tree = syntaxTree ( state ) ;
516-
517- // Find the node at the current position
518- let node = tree . resolveInner ( range . from , 1 ) ;
519-
520- // Traverse up to find a foldable node
521- while ( node ) {
522- if ( foldable ( state , node . from , node . to ) ) {
523- // This node is foldable, so it represents a section
524- return {
525- from : node . from ,
526- to : node . to ,
527- } ;
528- }
529- node = node . parent ;
530- }
531-
532- // If no foldable node found, return the original range
533- return range ;
534- }
535469
536470/**
537471 * Main task timer extension function
0 commit comments