feat(todo): quick add a small bar docked above the keyboard, as Todoist's
The developer's review of 3 Nov 2026 (ADR 0033, D23): in place of the tall sheet with its title and Add button, a rounded bar just above the keyboard, the list still in view behind a lighter barrier: the title, then a row of boxed buttons (+ for the description and the deadline, the date, the priority, the labels, the project), each its icon alone until something is set, and a send button. Its buttons show from the start rather than once typing begins (D15 had them come with the first letter). Where sheets are dialogs, the same bar in a dialog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
c7ad78f88d
commit
8438caa489
1 changed files with 301 additions and 173 deletions
|
|
@ -429,10 +429,10 @@ void main() {
|
|||
await tester.enterText(find.byType(TextField).first, title);
|
||||
// Add is on once there is a title.
|
||||
await tester.pump();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Add'));
|
||||
await tester.tap(find.byTooltip('Add'));
|
||||
await tester.pumpAndSettle();
|
||||
// The sheet stays for the next one; its close button closes it.
|
||||
await tester.tap(find.byTooltip('Close').last);
|
||||
// The bar stays for the next one; a tap beside it closes it.
|
||||
await tester.tapAt(const Offset(20, 20));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
|
|
@ -707,7 +707,7 @@ void main() {
|
|||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byKey(quickAddTitleKey), 'Envelopes');
|
||||
await tester.pump();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Add'));
|
||||
await tester.tap(find.byTooltip('Add'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final all = await tester.runAsync(() => tasks().all());
|
||||
|
|
@ -959,7 +959,7 @@ void main() {
|
|||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byKey(quickAddTitleKey), 'Call');
|
||||
await tester.pump();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Add'));
|
||||
await tester.tap(find.byTooltip('Add'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final stored = await tester.runAsync(() => tasks().all());
|
||||
|
|
@ -1055,7 +1055,7 @@ void main() {
|
|||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byKey(quickAddTitleKey), 'Call');
|
||||
await tester.pump();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Add'));
|
||||
await tester.tap(find.byTooltip('Add'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final stored = await tester.runAsync(() => tasks().all());
|
||||
|
|
@ -1245,28 +1245,52 @@ void main() {
|
|||
Future<void> open(WidgetTester tester, String text) async {
|
||||
await tester.tap(find.byTooltip('Add task'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.widgetWithText(ActionChip, 'Priority'),
|
||||
findsNothing,
|
||||
reason: 'the title alone at first',
|
||||
);
|
||||
// Its buttons from the start, as Todoist's bar above the keyboard
|
||||
// (the developer's review, 3 Nov 2026).
|
||||
expect(find.byTooltip('Priority'), findsOneWidget);
|
||||
await tester.enterText(find.byKey(quickAddTitleKey), text);
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
Future<void> add(WidgetTester tester) async {
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Add'));
|
||||
await tester.tap(find.byTooltip('Add'));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
testWidgets("a small bar docked just above the keyboard, as Todoist's, "
|
||||
'the list still in view above it', (tester) async {
|
||||
await start(tester, usedBefore: true);
|
||||
await goTab(tester, 'Inbox');
|
||||
await seed(tester, TaskContent(title: 'Call mum', projectId: inbox()));
|
||||
tester.view.viewInsets = const FakeViewPadding(bottom: 300);
|
||||
addTearDown(tester.view.resetViewInsets);
|
||||
|
||||
await tester.tap(find.byTooltip('Add task'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final bar = tester.getRect(find.byType(QuickAddBar));
|
||||
expect(bar.bottom, lessThanOrEqualTo(900 - 300), reason: 'above it');
|
||||
expect(bar.bottom, greaterThan(900 - 300 - 24), reason: 'just above');
|
||||
expect(bar.height, lessThan(200), reason: 'small');
|
||||
expect(
|
||||
tester.getRect(find.text('Call mum')).bottom,
|
||||
lessThan(bar.top),
|
||||
reason: 'the list in view',
|
||||
);
|
||||
expect(find.text('Add task'), findsNothing, reason: 'no title bar');
|
||||
});
|
||||
|
||||
testWidgets('typed tokens set the task, shown on its chips, a label '
|
||||
'unknown made', (tester) async {
|
||||
await start(tester, usedBefore: true);
|
||||
await goTab(tester, 'Inbox');
|
||||
await open(tester, 'Buy milk tomorrow 6pm p1 @Garden');
|
||||
|
||||
expect(find.widgetWithText(ActionChip, 'Priority 1'), findsOneWidget);
|
||||
expect(find.widgetWithText(ActionChip, '1 label'), findsOneWidget);
|
||||
expect(
|
||||
find.widgetWithText(QuickAddButton, 'Priority 1'),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(find.widgetWithText(QuickAddButton, '1 label'), findsOneWidget);
|
||||
expect(
|
||||
find.text('Tap a highlighted word to keep it as text.'),
|
||||
findsOneWidget,
|
||||
|
|
@ -1389,7 +1413,7 @@ void main() {
|
|||
await goTab(tester, 'Inbox');
|
||||
await open(tester, 'Pay tomorrow');
|
||||
|
||||
await tester.tap(find.widgetWithText(ActionChip, 'Tomorrow'));
|
||||
await tester.tap(find.widgetWithText(QuickAddButton, 'Tomorrow'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.widgetWithText(ListTile, 'Today').last);
|
||||
await tester.pumpAndSettle();
|
||||
|
|
@ -1400,7 +1424,7 @@ void main() {
|
|||
?.text,
|
||||
'Pay',
|
||||
);
|
||||
expect(find.widgetWithText(ActionChip, 'Today'), findsOneWidget);
|
||||
expect(find.widgetWithText(QuickAddButton, 'Today'), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(quickAddTitleKey));
|
||||
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown);
|
||||
|
|
@ -1874,9 +1898,9 @@ void main() {
|
|||
await tester.pumpAndSettle();
|
||||
await tester.enterText(find.byType(TextField).last, 'Socks');
|
||||
await tester.pump();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Add'));
|
||||
await tester.tap(find.byTooltip('Add'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byTooltip('Close').last);
|
||||
await tester.tapAt(const Offset(20, 20));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Sub-tasks 0/1'), findsOneWidget);
|
||||
|
||||
|
|
@ -2402,9 +2426,9 @@ void main() {
|
|||
);
|
||||
await tester.enterText(find.byKey(quickAddTitleKey), 'Between');
|
||||
await tester.pump();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Add'));
|
||||
await tester.tap(find.byTooltip('Add'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byTooltip('Close').last);
|
||||
await tester.tapAt(const Offset(20, 20));
|
||||
await tester.pumpAndSettle();
|
||||
expect(order(tester, ['Alpha', 'Bravo', 'Between']), [
|
||||
'Alpha',
|
||||
|
|
@ -2477,7 +2501,7 @@ void main() {
|
|||
);
|
||||
await tester.enterText(find.byKey(quickAddTitleKey), 'Later');
|
||||
await tester.pump();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Add'));
|
||||
await tester.tap(find.byTooltip('Add'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect((await stored(tester))['Later']!.date?.day, tomorrow);
|
||||
|
|
|
|||
Loading…
Reference in a new issue