feat(todo): the list scrolls to each task as quick add adds it, just above its bar

As Todoist's (the developer's review, 10 Nov 2026): the row of the task
added brings itself into view, just above quick add's bar on a phone,
within its list beside the dialog on the desktop; while quick add is
open, a screen's lists leave room at their end for the bar and the
keyboard, so that even the last task can rise above them, nothing in
view moving for it. A long list builds the rows near its view alone, so
the screen scrolls on down until the task's row is built.

Whats-New: Each task you add now scrolls into view, just above the add bar.
Whats-New-De: Jede neue Aufgabe rückt jetzt ins Bild, direkt über die Leiste zum Hinzufügen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-10 11:29:17 +01:00
commit 7f643aa00e
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -1025,6 +1025,84 @@ void main() {
await tester.pumpAndSettle();
}
group('the list scrolls to a task as quick add adds it, as '
"Todoist's (the developer's review, 10 Nov 2026)", () {
/// The Inbox holding [count] tasks.
Future<void> inboxOf(WidgetTester tester, int count) async {
await start(tester, usedBefore: true);
for (var index = 0; index < count; index++) {
await seed(
tester,
TaskContent(
title: 'Task $index',
projectId: inbox(),
position: index.toDouble(),
),
);
}
await goTab(tester, 'Inbox');
}
/// Adds [title] through the quick add bar open.
Future<void> add(WidgetTester tester, String title) async {
await tester.enterText(find.byKey(quickAddTitleKey), title);
await tester.pump();
await tester.tap(find.byTooltip('Add'));
await tester.pumpAndSettle();
}
double barTop(WidgetTester tester) =>
tester.getTopLeft(find.byType(QuickAddBar)).dy;
testWidgets('on a phone, each one just above the bar, however long '
'the list', (tester) async {
await inboxOf(tester, 25);
await tester.tap(find.byTooltip('Add task'));
await tester.pumpAndSettle();
for (final title in ['Newest', 'Newer still']) {
await add(tester, title);
final row = tester.getRect(find.text(title));
expect(row.bottom, lessThanOrEqualTo(barTop(tester)));
expect(row.bottom, greaterThan(barTop(tester) - 120));
}
});
testWidgets('a list that has room for it stays where it is', (
tester,
) async {
await inboxOf(tester, 2);
final top = tester.getTopLeft(find.text('Task 0'));
await tester.tap(find.byTooltip('Add task'));
await tester.pumpAndSettle();
await add(tester, 'Newest');
expect(tester.getTopLeft(find.text('Task 0')), top);
expect(find.text('Newest'), findsOneWidget);
});
testWidgets('on the desktop, beside the dialog, into view', (
tester,
) async {
debugDefaultTargetPlatformOverride = TargetPlatform.linux;
addTearDown(() => debugDefaultTargetPlatformOverride = null);
await inboxOf(tester, 25);
await tester.tap(find.byTooltip('Add task'));
await tester.pumpAndSettle();
await add(tester, 'Newest');
final row = tester.getRect(find.text('Newest'));
expect(
row.bottom,
lessThanOrEqualTo(
tester.view.physicalSize.height / tester.view.devicePixelRatio,
),
);
expect(row.top, greaterThan(0));
debugDefaultTargetPlatformOverride = null;
});
});
testWidgets('a task added in the Inbox shows there, sealed on its way', (
tester,
) async {
@ -4857,6 +4935,11 @@ void main() {
await tester.tapAt(const Offset(20, 20));
await tester.pumpAndSettle();
expect(find.text('Sub-tasks 0/1'), findsOneWidget);
// The sub-task added was brought into view above quick add's bar.
await tester.ensureVisible(
find.byTooltip('Task options', skipOffstage: false),
);
await tester.pumpAndSettle();
await tester.tap(find.byTooltip('Task options'));
await tester.pumpAndSettle();