(task: TaskInfo, date?: Date)
| 1622 | } |
| 1623 | |
| 1624 | async toggleRecurringTaskComplete(task: TaskInfo, date?: Date): Promise<TaskInfo> { |
| 1625 | const file = this.plugin.app.vault.getAbstractFileByPath(task.path); |
| 1626 | if (!(file instanceof TFile)) { |
| 1627 | throw new Error(`Cannot find task file: ${task.path}`); |
| 1628 | } |
| 1629 | |
| 1630 | // Get fresh task data to ensure we have the latest completion state |
| 1631 | const freshTask = (await this.plugin.cacheManager.getTaskInfo(task.path)) || task; |
| 1632 | |
| 1633 | if (!freshTask.recurrence) { |
| 1634 | throw new Error("Task is not recurring"); |
| 1635 | } |
| 1636 | |
| 1637 | const recurringPlan = buildRecurringTaskCompletePlan({ |
| 1638 | freshTask, |
| 1639 | targetDate: this.getRecurringTaskActionDate(freshTask, date), |
| 1640 | currentTimestamp: getCurrentTimestamp(), |
| 1641 | maintainDueDateOffsetInRecurring: this.plugin.settings.maintainDueDateOffsetInRecurring, |
| 1642 | }); |
| 1643 | const { updatedTask, dateStr, newComplete, targetDate } = recurringPlan; |
| 1644 | |
| 1645 | // Step 2: Persist to file |
| 1646 | await this.plugin.app.fileManager.processFrontMatter(file, (frontmatter) => { |
| 1647 | const completeInstancesField = this.plugin.fieldMapper.toUserField("completeInstances"); |
| 1648 | const skippedInstancesField = this.plugin.fieldMapper.toUserField("skippedInstances"); |
| 1649 | const dateModifiedField = this.plugin.fieldMapper.toUserField("dateModified"); |
| 1650 | const scheduledField = this.plugin.fieldMapper.toUserField("scheduled"); |
| 1651 | const dueField = this.plugin.fieldMapper.toUserField("due"); |
| 1652 | const recurrenceField = this.plugin.fieldMapper.toUserField("recurrence"); |
| 1653 | const googleCalendarExceptionOriginalScheduledField = |
| 1654 | this.plugin.fieldMapper.toUserField("googleCalendarExceptionOriginalScheduled"); |
| 1655 | const googleCalendarMovedOriginalDatesField = this.plugin.fieldMapper.toUserField( |
| 1656 | "googleCalendarMovedOriginalDates" |
| 1657 | ); |
| 1658 | |
| 1659 | applyRecurringTaskCompleteFrontmatterChange({ |
| 1660 | frontmatter, |
| 1661 | completeInstancesField, |
| 1662 | skippedInstancesField, |
| 1663 | dateModifiedField, |
| 1664 | scheduledField, |
| 1665 | dueField, |
| 1666 | recurrenceField, |
| 1667 | googleCalendarExceptionOriginalScheduledField, |
| 1668 | googleCalendarMovedOriginalDatesField, |
| 1669 | plan: recurringPlan, |
| 1670 | }); |
| 1671 | }); |
| 1672 | |
| 1673 | // Step 2b: Reset checkboxes in task body when completing (if setting enabled) |
| 1674 | if (newComplete && this.plugin.settings.resetCheckboxesOnRecurrence) { |
| 1675 | const currentContent = await this.plugin.app.vault.read(file); |
| 1676 | const { frontmatter: frontmatterText, body } = splitFrontmatterAndBody(currentContent); |
| 1677 | const { content: resetBody, changed } = resetMarkdownCheckboxes(body); |
| 1678 | |
| 1679 | if (changed) { |
| 1680 | const frontmatterBlock = |
| 1681 | frontmatterText !== null ? `---\n${frontmatterText}\n---\n\n` : ""; |
no test coverage detected