feat(train): Maps shows every route on the map, above the list or beside it (ADR 0030, D60)
The instance's map with every route drawn, fitted to them all, a route tapped opening its planner. On phones the map stands above the list; from expanded windows on the two are panes side by side, as Material's list-detail layout. Without a route to draw, the list alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
064c44bfa5
commit
220816884c
1 changed files with 263 additions and 6 deletions
|
|
@ -44,6 +44,7 @@ import 'package:halkyon_train_flutter/src/feature/route/model/route.dart';
|
|||
import 'package:halkyon_train_flutter/src/feature/workout/data/workout_repository.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/model/workout.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/widget/week_card.dart';
|
||||
import 'package:halkyon_train_flutter/src/tabs/maps_tab.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
|
|
@ -2548,6 +2549,102 @@ void main() {
|
|||
expect(find.text("Your instance doesn't plan routes."), findsOneWidget);
|
||||
});
|
||||
|
||||
group('on the Maps tab (D60)', () {
|
||||
Future<void> saveTwo() async {
|
||||
for (final (name, end) in [
|
||||
('Isar', const LatLng(48.12, 11.58)),
|
||||
('Englischer Garten', const LatLng(48.16, 11.6)),
|
||||
]) {
|
||||
await routes.save(
|
||||
RouteContent(
|
||||
name: name,
|
||||
profile: RouteProfile.run,
|
||||
waypoints: [const LatLng(48.137, 11.575), end],
|
||||
planned: straightRoute([const LatLng(48.137, 11.575), end]),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
List<Polyline<Object>> lines(WidgetTester tester) => [
|
||||
for (final layer in tester.widgetList<PolylineLayer<Object>>(
|
||||
find.descendant(
|
||||
of: find.byType(MapsTab),
|
||||
matching: find.byType(PolylineLayer<Object>),
|
||||
),
|
||||
))
|
||||
...layer.polylines,
|
||||
];
|
||||
|
||||
testWidgets('on a phone, every route on a map above the list', (
|
||||
tester,
|
||||
) async {
|
||||
await saveTwo();
|
||||
await openRoutes(tester);
|
||||
|
||||
expect(lines(tester), hasLength(2));
|
||||
final map = find.descendant(
|
||||
of: find.byType(MapsTab),
|
||||
matching: find.byType(FlutterMap),
|
||||
);
|
||||
expect(
|
||||
tester.getBottomLeft(map).dy,
|
||||
lessThanOrEqualTo(tester.getTopLeft(find.text('Isar')).dy),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('a route tapped on the map opens', (tester) async {
|
||||
await routes.save(
|
||||
RouteContent(
|
||||
name: 'Isar',
|
||||
profile: RouteProfile.run,
|
||||
waypoints: const [LatLng(48.137, 11.575), LatLng(48.12, 11.58)],
|
||||
planned: straightRoute(const [
|
||||
LatLng(48.137, 11.575),
|
||||
LatLng(48.12, 11.58),
|
||||
]),
|
||||
),
|
||||
);
|
||||
await openRoutes(tester);
|
||||
|
||||
// The camera fits the one route, whose middle is the map's.
|
||||
await tapMap(tester, Offset.zero);
|
||||
expect(find.text('Route'), findsOneWidget);
|
||||
expect(find.text('Isar'), findsWidgets);
|
||||
});
|
||||
|
||||
testWidgets('from expanded windows on, the list and the map side by '
|
||||
'side', (tester) async {
|
||||
await saveTwo();
|
||||
await openRoutes(tester);
|
||||
tester.view.physicalSize = const Size(1280, 800);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final map = find.descendant(
|
||||
of: find.byType(MapsTab),
|
||||
matching: find.byType(FlutterMap),
|
||||
);
|
||||
expect(
|
||||
tester.getTopLeft(map).dx,
|
||||
greaterThanOrEqualTo(tester.getTopRight(find.text('Isar')).dx),
|
||||
);
|
||||
expect(lines(tester), hasLength(2));
|
||||
});
|
||||
|
||||
testWidgets('without routes, no map', (tester) async {
|
||||
await openRoutes(tester);
|
||||
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(MapsTab),
|
||||
matching: find.byType(FlutterMap),
|
||||
),
|
||||
findsNothing,
|
||||
);
|
||||
expect(find.text('No routes yet'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('a route is opened, deleted after asking and brought back', (
|
||||
tester,
|
||||
) async {
|
||||
|
|
|
|||
Loading…
Reference in a new issue