Some checks failed
CI / Windows build (push) Has been cancelled
Notes now use the single performant inking engine (PenCanvas) instead of the old ink_canvas, per "all note features on the pen-first canvas". - ink_stroke_adapter: pure InkStroke<->PenStroke bridge (normalize against a logical note page; drop non-freehand shapes/text). Round-trip tested. - pen_palette_widgets: shared M3 ToolButton/PaletteDivider/RoundIconButton so PDF + note editors use identical chrome (PenEditorScreen migrated to them; its private copies deleted). - PenNoteScreen: PenCanvas over a white logical page, undo/redo, title, save -> Note.strokes (+ local OCR for search). Pressure curve, eraser size/mode and palm rejection all inherited from the shared canvas. - Route home (new/open) + search note hits -> PenNoteScreen; remove the now-redundant "Pen Canvas (beta)" spike button; delete the dead old note_editor_screen. Tests: ink_stroke_adapter (5) + pen_note_screen widget (load + commit, 2). flutter analyze: 0 issues. Full suite: 265/265.
77 lines
2.7 KiB
Dart
77 lines
2.7 KiB
Dart
// Screen-level guard for the pen-first note editor: an existing note's ink
|
|
// strokes load onto the PenCanvas via the adapter, and a stylus pass commits a
|
|
// new stroke. Exercises the real PenNoteScreen (no DB needed — persistence only
|
|
// runs on save).
|
|
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import 'package:badnote/editor/canvas/pen_canvas.dart';
|
|
import 'package:badnote/editor/canvas/pen_note_screen.dart';
|
|
import 'package:badnote/models/ink_point.dart';
|
|
import 'package:badnote/models/ink_stroke.dart';
|
|
import 'package:badnote/models/note.dart';
|
|
import 'package:badnote/models/pen_tool.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
Note noteWith(List<InkStroke> strokes) => Note(
|
|
id: 'n1',
|
|
title: 'Test',
|
|
strokes: strokes,
|
|
createdAt: DateTime.fromMillisecondsSinceEpoch(0),
|
|
updatedAt: DateTime.fromMillisecondsSinceEpoch(0),
|
|
);
|
|
|
|
InkStroke freehand() => InkStroke(
|
|
id: 's1',
|
|
points: const [
|
|
InkPoint(x: 100, y: 200, timestamp: 0),
|
|
InkPoint(x: 300, y: 400, timestamp: 0),
|
|
InkPoint(x: 500, y: 700, timestamp: 0),
|
|
],
|
|
tool: PenTool.pen,
|
|
createdAt: DateTime.fromMillisecondsSinceEpoch(0),
|
|
);
|
|
|
|
int canvasStrokeCount(WidgetTester tester) =>
|
|
tester.widget<PenCanvas>(find.byType(PenCanvas)).strokes.length;
|
|
|
|
testWidgets('loads an existing note\'s ink strokes onto the canvas',
|
|
(tester) async {
|
|
SharedPreferences.setMockInitialValues({});
|
|
await tester.pumpWidget(ProviderScope(
|
|
child: MaterialApp(home: PenNoteScreen(note: noteWith([freehand()]))),
|
|
));
|
|
await tester.pump(); // let PenConfig load
|
|
|
|
expect(find.byType(PenCanvas), findsOneWidget);
|
|
expect(canvasStrokeCount(tester), 1,
|
|
reason: 'the note\'s freehand stroke should load via the adapter');
|
|
});
|
|
|
|
testWidgets('a stylus pass commits a new stroke', (tester) async {
|
|
SharedPreferences.setMockInitialValues({});
|
|
await tester.pumpWidget(ProviderScope(
|
|
child: MaterialApp(home: PenNoteScreen(note: noteWith([]))),
|
|
));
|
|
await tester.pump();
|
|
|
|
expect(canvasStrokeCount(tester), 0);
|
|
|
|
final center = tester.getCenter(find.byType(PenCanvas));
|
|
final g = await tester.startGesture(center, kind: PointerDeviceKind.stylus);
|
|
await g.moveBy(const Offset(40, 30));
|
|
await g.moveBy(const Offset(30, 20));
|
|
await g.up();
|
|
await tester.pump();
|
|
|
|
expect(canvasStrokeCount(tester), 1,
|
|
reason: 'the drawn stroke should be committed to the canvas');
|
|
});
|
|
}
|