Skip to content

Commit 1cdc0f4

Browse files
committed
Complete recurring tasks by setting their start date to the next recurrence date
Signed-off-by: Sunik Kupfer <[email protected]>
1 parent 3429db3 commit 1cdc0f4

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

src/models/task.js

+32-3
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ export default class Task {
9595
this._completed = !!comp
9696
this._completedDate = comp ? comp.toJSDate() : null
9797
this._completedDateMoment = moment(this._completedDate, 'YYYYMMDDTHHmmss')
98-
const recur = this.vtodo.getFirstPropertyValue('rrule')
99-
this._recurring = !!recur
98+
this._recurrence = this.vtodo.getFirstPropertyValue('rrule')
10099
this._status = this.vtodo.getFirstPropertyValue('status')
101100
this._note = this.vtodo.getFirstPropertyValue('description') || ''
102101
this._related = this.getParent()?.getFirstValue() || null
@@ -331,8 +330,17 @@ export default class Task {
331330
return this._completedDateMoment.clone()
332331
}
333332

333+
get recurrence() {
334+
return this._recurrence
335+
}
336+
334337
get recurring() {
335-
return this._recurring
338+
if (this._start === null || this._recurrence === null) {
339+
return false
340+
}
341+
const iter = this._recurrence.iterator(this.start)
342+
iter.next()
343+
return iter.next() !== null
336344
}
337345

338346
get status() {
@@ -680,6 +688,27 @@ export default class Task {
680688
).toSeconds()
681689
}
682690

691+
/**
692+
* For completing a recurring task, tries to set the task start date to the next recurrence date.
693+
*
694+
* Does nothing if we are at the end of the recurrence (RRULE:UNTIL was reached).
695+
*/
696+
completeRecurring() {
697+
// Get recurrence iterator, starting at start date
698+
const iter = this.recurrence.iterator(this.start)
699+
// Skip the start date itself
700+
iter.next()
701+
// If there is a next recurrence, update the start date to next recurrence date
702+
const nextRecurrence = iter.next()
703+
if (nextRecurrence !== null) {
704+
this.start = nextRecurrence
705+
// If the due date now lies before start date, clear it
706+
if (this.due !== null && this.due.compare(this.start) < 0) {
707+
this.due = null
708+
}
709+
}
710+
}
711+
683712
/**
684713
* Checks if the task matches the search query
685714
*

src/store/tasks.js

+6
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,12 @@ const actions = {
10381038
if (task.calendar.isSharedWithMe && task.class !== 'PUBLIC') {
10391039
return
10401040
}
1041+
// Don't complete a task if it is still recurring, but update its start date instead
1042+
if (task.recurring) {
1043+
task.completeRecurring()
1044+
await context.dispatch('updateTask', task)
1045+
return
1046+
}
10411047
if (task.completed) {
10421048
await context.dispatch('setPercentComplete', { task, complete: 0 })
10431049
} else {

0 commit comments

Comments
 (0)