feat: add D-pad navigation for phones

This commit is contained in:
randogoth 2026-10-13 11:47:01 +03:00
parent 414f8e8484
commit b3df7fba9f
6 changed files with 380 additions and 31 deletions

View file

@ -172,6 +172,115 @@ void main() {
expect(find.byType(NoteEditorScreen), findsNothing);
});
testWidgets('holding the D-pad center goes back to the list',
(tester) async {
await tester.runAsync(() async {
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (context) => TextButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => NoteEditorScreen(
note: note, notesDirectoryPath: note.parent.path),
),
),
child: const Text('list'),
),
),
));
await tester.tap(find.text('list'));
await tester.pump();
await Future<void>.delayed(const Duration(milliseconds: 100));
});
await tester.pumpAndSettle();
await tester.sendKeyDownEvent(LogicalKeyboardKey.select);
await tester.pump(const Duration(milliseconds: 200));
await tester.sendKeyUpEvent(LogicalKeyboardKey.select);
await tester.pumpAndSettle();
expect(find.byType(NoteEditorScreen), findsOneWidget,
reason: 'a short press stays in the note');
await tester.sendKeyDownEvent(LogicalKeyboardKey.select);
await tester.pump(const Duration(milliseconds: 600));
await tester.sendKeyUpEvent(LogicalKeyboardKey.select);
await tester.pumpAndSettle();
expect(find.byType(NoteEditorScreen), findsNothing);
});
testWidgets('D-pad Right opens the menu and Left goes back to the list',
(tester) async {
await tester.runAsync(() async {
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (context) => TextButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => NoteEditorScreen(
note: note, notesDirectoryPath: note.parent.path),
),
),
child: const Text('list'),
),
),
));
await tester.tap(find.text('list'));
await tester.pump();
await Future<void>.delayed(const Duration(milliseconds: 100));
});
await tester.pumpAndSettle();
await _press(tester, LogicalKeyboardKey.arrowRight);
expect(find.text('Save'), findsOneWidget);
// Share has focus first; Down moves to Save, which closes the menu.
await _press(tester, LogicalKeyboardKey.arrowDown);
await _press(tester, LogicalKeyboardKey.select);
expect(find.text('Save'), findsNothing);
await _press(tester, LogicalKeyboardKey.keyE, control: true);
await _press(tester, LogicalKeyboardKey.arrowRight);
expect(find.text('Save'), findsNothing,
reason: 'arrows move the caret in edit mode');
await _press(tester, LogicalKeyboardKey.arrowLeft);
expect(find.byType(NoteEditorScreen), findsOneWidget);
await _press(tester, LogicalKeyboardKey.keyE, control: true);
await _press(tester, LogicalKeyboardKey.arrowLeft);
expect(find.byType(NoteEditorScreen), findsNothing);
});
testWidgets('the D-pad moves past the font size slider in the menu',
(tester) async {
await pumpEditor(tester);
await _press(tester, LogicalKeyboardKey.arrowRight);
String focusedLabel() {
final context = FocusManager.instance.primaryFocus!.context!;
if (context.findAncestorWidgetOfExactType<Slider>() != null ||
context.widget is Slider) {
return 'slider';
}
final texts = find.descendant(
of: find.byWidget(context.widget), matching: find.byType(Text));
return tester.widgetList<Text>(texts).map((t) => t.data).join();
}
// Share, Save, Autosave, slider, Preview.
for (var i = 0; i < 3; i++) {
await _press(tester, LogicalKeyboardKey.arrowDown);
}
expect(focusedLabel(), 'slider');
await _press(tester, LogicalKeyboardKey.arrowRight);
expect(tester.widget<MarkdownView>(find.byType(MarkdownView)).fontSize, 18,
reason: 'Right adjusts the slider');
await _press(tester, LogicalKeyboardKey.arrowDown);
expect(focusedLabel(), 'Preview Mode');
});
testWidgets('the open note follows theme switches', (tester) async {
final mode = ValueNotifier(ThemeMode.light);
await tester.runAsync(() async {