Files
2026-04-03 21:55:55 +02:00

7.9 KiB

phase: 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks plan: 02 subsystem: ui, database, domain tags: [flutter, drift, riverpod, pre-population, recurring-tasks, calendar, interval-window] # Dependency graph requires: - phase: 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks plan: 11-01 provides: Always-enabled checkboxes and today-base completeTask behavior provides: - watchAllActiveRecurringTasks and watchAllActiveRecurringTasksInRoom DAO queries - watchCompletionsInRange DAO query for period-completion filtering - CalendarDayState.prePopulatedTasks field - _isInCurrentIntervalWindow and _calculatePreviousDueDate pre-population helpers - calendarDayProvider and roomCalendarDayProvider pre-population logic - "Demnächst" section with 0.55 opacity rendering in CalendarDayList affects: - Home screen calendar day view (pre-populated tasks now visible) - Room-scoped calendar view (same pre-population logic) - Celebration state (now checks prePopulatedTasks.isEmpty too) # Tech tracking tech-stack: added: [] patterns: - "Interval window pre-population: query-time virtual instances, no schema migration" - "Period-completion filtering: watchCompletionsInRange excludes already-completed tasks" - "Total-month arithmetic for _subtractMonths: avoids year-boundary bugs with negative months" - "0.55 opacity for pre-populated task rows via Opacity widget wrapper" key-files: created: [] modified: - lib/features/home/data/calendar_dao.dart - lib/features/home/domain/calendar_models.dart - lib/features/home/presentation/calendar_providers.dart - lib/features/home/presentation/calendar_day_list.dart - lib/features/home/presentation/calendar_task_row.dart - test/features/home/data/calendar_dao_test.dart key-decisions: - "D-03: Pre-population via query-time virtual instances — no schema migration, no stored virtual rows" - "D-04: _subtractMonths uses total-month arithmetic (year*12+month-1) to correctly handle January-boundary crossings" - "D-05: Pre-populated tasks rendered in 'Demnächst' section below day tasks with 0.55 Opacity" - "D-06: Celebration state now includes prePopulatedTasks.isEmpty — pre-populated tasks prevent celebration" patterns-established: - "Interval window: selected date AFTER previousDue (exclusive) AND BEFORE nextDueDate (exclusive)" - "Period completion filter: watchCompletionsInRange(taskId, prevDue, nextDue+1day)" - "Muted pre-population UI: Opacity(0.55) wrapping ListTile, isPrePopulated flag propagated through widget tree" requirements-completed: - TM-03 - TM-04 - TM-05 # Metrics duration: ~15min completed: 2026-04-03

Phase 11 Plan 02: Pre-populate Recurring Tasks on Interval Window Summary

Interval-window pre-population via query-time virtual instances with period-completion filtering and 0.55 opacity muted visual distinction

Performance

  • Duration: ~15 min
  • Started: 2026-04-03
  • Completed: 2026-04-03
  • Tasks: 2
  • Files modified: 6

Accomplishments

  • Added watchAllActiveRecurringTasks() and watchAllActiveRecurringTasksInRoom(roomId) to CalendarDao — fetch all active tasks for pre-population source data
  • Added watchCompletionsInRange(taskId, start, end) to CalendarDao — check if a task was completed in the current interval period (prevents re-showing completed tasks)
  • Extended CalendarDayState with prePopulatedTasks field (default empty for backward compatibility); updated isEmpty getter to include prePopulatedTasks.isEmpty
  • Added _isInCurrentIntervalWindow() helper: determines if a task's current interval window includes selectedDate (selected is after previousDue and before nextDueDate)
  • Added _calculatePreviousDueDate() helper: reverse-calculates start of current interval window by subtracting one interval
  • Rewrote calendarDayProvider and roomCalendarDayProvider to combine three streams: due-today, overdue, and pre-populated virtual instances with period-completion exclusion
  • Added isPrePopulated parameter to CalendarTaskRow with Opacity(0.55) wrapper for muted visual style
  • Rendered "Demnächst" section in CalendarDayList below day tasks, with muted section header and isPrePopulated: true rows
  • Added 9 new DAO tests for watchAllActiveRecurringTasks, watchAllActiveRecurringTasksInRoom, watchCompletionsInRange

Task Commits

Each task was committed atomically:

  1. Task 1: DAO queries, CalendarDayState model, pre-population provider - 9a67c51 (feat)
  2. Task 2: UI rendering with muted visual distinction - 8cbe989 (feat)

Files Created/Modified

  • lib/features/home/data/calendar_dao.dart — Added watchAllActiveRecurringTasks(), watchAllActiveRecurringTasksInRoom(), watchCompletionsInRange()
  • lib/features/home/domain/calendar_models.dart — Added prePopulatedTasks field with default empty, updated isEmpty
  • lib/features/home/presentation/calendar_providers.dart — Added _isInCurrentIntervalWindow, _calculatePreviousDueDate, _subtractMonths helpers; rewrote both providers with pre-population logic; added IntervalType and database.dart imports
  • lib/features/home/presentation/calendar_day_list.dart — Added "Demnächst" section, updated _buildAnimatedTaskRow with isPrePopulated, updated _CompletingTaskRow, updated celebration check, updated cleanup loop
  • lib/features/home/presentation/calendar_task_row.dart — Added isPrePopulated parameter and Opacity(0.55) wrapper
  • test/features/home/data/calendar_dao_test.dart — Added 9 tests across 3 new test groups; added drift/drift.dart import for Value

Decisions Made

  • Pre-population uses query-time virtual instances — no schema migration, no stored virtual rows. Provider layer computes which tasks appear on a given day by checking their interval window.
  • _subtractMonths uses total-month arithmetic (year*12 + month - 1 - months) instead of the plan's proposed formula, which had a year-boundary bug for months <= 0 (e.g. January - 1 month would incorrectly stay in the same year with Dart's truncation division).
  • Celebration state updated to check prePopulatedTasks.isEmpty — a day with only pre-populated tasks does not show the celebration screen (tasks still need doing).

Deviations from Plan

Auto-fixed Issues

1. [Rule 1 - Bug] Fixed _subtractMonths year-boundary arithmetic

  • Found during: Task 1
  • Issue: The plan's proposed _subtractMonths formula used (targetMonth - 1) ~/ 12 for year calculation. In Dart, ~/ is truncation-toward-zero division, so (-1) ~/ 12 = 0 (not -1). This means subtracting 1 month from January 2026 would produce year 2026 instead of 2025.
  • Fix: Replaced with total-month arithmetic: totalMonths = date.year * 12 + (date.month - 1) - months, then targetYear = totalMonths ~/ 12, normalizedMonth = (totalMonths % 12) + 1. This is always correct for any combination of year and months.
  • Files modified: lib/features/home/presentation/calendar_providers.dart
  • Commit: 9a67c51

Known Stubs

None.

User Setup Required

None — no external service configuration required.

Next Phase Readiness

  • Pre-population of recurring tasks fully implemented
  • Phase 11 (Issue #3) complete — both plans executed
  • No blockers

Self-Check: PASSED

  • FOUND: lib/features/home/data/calendar_dao.dart
  • FOUND: lib/features/home/domain/calendar_models.dart
  • FOUND: lib/features/home/presentation/calendar_providers.dart
  • FOUND: lib/features/home/presentation/calendar_day_list.dart
  • FOUND: lib/features/home/presentation/calendar_task_row.dart
  • FOUND: test/features/home/data/calendar_dao_test.dart
  • FOUND: commit 9a67c51 (Task 1 - DAO queries + provider logic)
  • FOUND: commit 8cbe989 (Task 2 - UI rendering)

Phase: 11-issue-3-tasks-management-allow-task-checking-anytime-and-pre-populate-recurring-tasks Completed: 2026-04-03