feat(todo): recurring tasks, set through a picker (ADR 0033, D7)
A task's date may recur: every n days, weeks (on which weekdays), months (on its day, or its nth or last weekday), years, from its date or from when it is done, until a day or for n times. Done, it moves on to the next day after both its date and today, its deadline as far, its time kept, its done sub-tasks open again and when it was done kept in its payload; undo writes all of it back. The date sheet offers the rules that fit the task's day and a rule of the person's own; rows show a recurring date with its own icon, the task sheet the rule in words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
030c62ddde
commit
aa013f5a00
1 changed files with 1655 additions and 25 deletions
|
|
@ -8,8 +8,10 @@ import 'package:halkyon_todo_flutter/src/feature/label/data/label_repository.dar
|
|||
import 'package:halkyon_todo_flutter/src/feature/project/data/project_repository.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/section/data/section_repository.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/task/data/task_repository.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/task/model/repeat.dart';
|
||||
import 'package:halkyon_todo_flutter/src/feature/task/model/task.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
import '../support/memory_content_key_gateway.dart';
|
||||
|
|
@ -382,6 +384,54 @@ void main() {
|
|||
expect(title.style?.decoration, TextDecoration.lineThrough);
|
||||
});
|
||||
|
||||
testWidgets('a task set to repeat every day, done, comes again '
|
||||
'tomorrow, when it was done kept', (tester) async {
|
||||
final today = Day.of(DateTime.now());
|
||||
await start(tester, usedBefore: true);
|
||||
await seed(
|
||||
tester,
|
||||
TaskContent(
|
||||
title: 'Stretch',
|
||||
projectId: inbox(),
|
||||
date: TaskDate(today),
|
||||
),
|
||||
);
|
||||
await goTab(tester, 'Inbox');
|
||||
await tester.tap(find.text('Stretch'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(
|
||||
find.widgetWithIcon(ListTile, LucideIcons.calendar).last,
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.widgetWithText(ListTile, 'Repeat'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('Every day'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Every day'), findsOneWidget, reason: 'in the sheet');
|
||||
await tester.tap(find.byTooltip('Close').last);
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.widgetWithText(ListTile, 'Stretch'),
|
||||
matching: find.byIcon(LucideIcons.repeat),
|
||||
),
|
||||
findsOneWidget,
|
||||
);
|
||||
|
||||
await tester.tap(find.byTooltip('Mark as done'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Stretch'), findsOneWidget, reason: 'still to do');
|
||||
expect(find.text('Tomorrow'), findsOneWidget);
|
||||
final stored = (await tester.runAsync(() => tasks().all()))!.single;
|
||||
expect(
|
||||
stored.content?.date,
|
||||
TaskDate(today.plus(1), repeat: const Repeat(RepeatUnit.day)),
|
||||
);
|
||||
expect(stored.content?.completions, hasLength(1));
|
||||
expect(stored.content?.completed, isFalse);
|
||||
});
|
||||
|
||||
testWidgets('Today puts what is overdue first; Reschedule moves it to '
|
||||
'the day picked', (tester) async {
|
||||
final today = Day.of(DateTime.now());
|
||||
|
|
|
|||
Loading…
Reference in a new issue