fix(train): the maps stop at zoom 18, beyond which they drew nothing

vector_map_tiles draws its tiles as pictures and stops at zoom 18, while
the maps let people zoom further, onto a grey map.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-30 23:00:49 +01:00
commit 32c94aa601
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
5 changed files with 28 additions and 0 deletions

View file

@ -8,6 +8,10 @@ import 'package:vector_map_tiles/vector_map_tiles.dart';
import 'package:vector_tile_renderer/vector_tile_renderer.dart' import 'package:vector_tile_renderer/vector_tile_renderer.dart'
show SpriteIndexReader, ThemeReader; show SpriteIndexReader, ThemeReader;
/// The closest every map zooms: the tile layer, drawing the tiles as
/// pictures (vector_map_tiles' raster mode), draws nothing beyond zoom 18.
const mapMaxZoom = 18.0;
/// Builds the map's tile layer for a source: [vectorTiles] in the app, none /// Builds the map's tile layer for a source: [vectorTiles] in the app, none
/// in widget tests, which reach no network. /// in widget tests, which reach no network.
typedef MapTiles = Widget Function(MapSource source); typedef MapTiles = Widget Function(MapSource source);

View file

@ -6,6 +6,7 @@ import 'package:halkyon_app/halkyon_app.dart';
import 'package:halkyon_train_client/halkyon_train_client.dart' show MapSource; import 'package:halkyon_train_client/halkyon_train_client.dart' show MapSource;
import 'package:halkyon_train_flutter/l10n/app_localizations.dart'; import 'package:halkyon_train_flutter/l10n/app_localizations.dart';
import 'package:halkyon_train_flutter/src/app/train_dependencies.dart'; import 'package:halkyon_train_flutter/src/app/train_dependencies.dart';
import 'package:halkyon_train_flutter/src/feature/map/widget/map_tiles.dart';
import 'package:halkyon_train_flutter/src/feature/plan/model/plan.dart'; import 'package:halkyon_train_flutter/src/feature/plan/model/plan.dart';
import 'package:halkyon_train_flutter/src/feature/plan/widget/plan_texts.dart'; import 'package:halkyon_train_flutter/src/feature/plan/widget/plan_texts.dart';
import 'package:halkyon_train_flutter/src/feature/recording/bloc/recording_bloc.dart'; import 'package:halkyon_train_flutter/src/feature/recording/bloc/recording_bloc.dart';
@ -529,6 +530,7 @@ class _RecordingMapState() extends State<_RecordingMap> {
FlutterMap( FlutterMap(
mapController: _map, mapController: _map,
options: MapOptions( options: MapOptions(
maxZoom: mapMaxZoom,
initialCenter: _here ?? const LatLng(50, 10), initialCenter: _here ?? const LatLng(50, 10),
initialZoom: _here == null ? 4 : 16, initialZoom: _here == null ? 4 : 16,
interactionOptions: const InteractionOptions( interactionOptions: const InteractionOptions(

View file

@ -5,6 +5,7 @@ import 'package:halkyon_train_client/halkyon_train_client.dart' show MapSource;
import 'package:halkyon_train_flutter/l10n/app_localizations.dart'; import 'package:halkyon_train_flutter/l10n/app_localizations.dart';
import 'package:halkyon_train_flutter/src/app/train_dependencies.dart'; import 'package:halkyon_train_flutter/src/app/train_dependencies.dart';
import 'package:halkyon_train_flutter/src/feature/map/data/offline_maps.dart'; import 'package:halkyon_train_flutter/src/feature/map/data/offline_maps.dart';
import 'package:halkyon_train_flutter/src/feature/map/widget/map_tiles.dart';
import 'package:halkyon_train_flutter/src/feature/recording/data/recorder_platform.dart'; import 'package:halkyon_train_flutter/src/feature/recording/data/recorder_platform.dart';
import 'package:halkyon_train_flutter/src/feature/recording/widget/recording_texts.dart'; import 'package:halkyon_train_flutter/src/feature/recording/widget/recording_texts.dart';
import 'package:halkyon_train_flutter/src/feature/route/bloc/place_search_cubit.dart'; import 'package:halkyon_train_flutter/src/feature/route/bloc/place_search_cubit.dart';
@ -255,6 +256,7 @@ class _RouteMapState() extends State<_RouteMap> {
FlutterMap( FlutterMap(
mapController: _map, mapController: _map,
options: MapOptions( options: MapOptions(
maxZoom: mapMaxZoom,
initialCameraFit: _fit.length > 1 initialCameraFit: _fit.length > 1
? CameraFit.coordinates( ? CameraFit.coordinates(
coordinates: _fit, coordinates: _fit,

View file

@ -4,6 +4,7 @@ import 'package:halkyon_app/halkyon_app.dart';
import 'package:halkyon_train_client/halkyon_train_client.dart' show MapSource; import 'package:halkyon_train_client/halkyon_train_client.dart' show MapSource;
import 'package:halkyon_train_flutter/l10n/app_localizations.dart'; import 'package:halkyon_train_flutter/l10n/app_localizations.dart';
import 'package:halkyon_train_flutter/src/app/train_dependencies.dart'; import 'package:halkyon_train_flutter/src/app/train_dependencies.dart';
import 'package:halkyon_train_flutter/src/feature/map/widget/map_tiles.dart';
import 'package:halkyon_train_flutter/src/feature/plan/widget/plan_texts.dart'; import 'package:halkyon_train_flutter/src/feature/plan/widget/plan_texts.dart';
import 'package:halkyon_train_flutter/src/feature/recording/model/recording.dart'; import 'package:halkyon_train_flutter/src/feature/recording/model/recording.dart';
import 'package:halkyon_train_flutter/src/feature/recording/widget/recording_texts.dart'; import 'package:halkyon_train_flutter/src/feature/recording/widget/recording_texts.dart';
@ -386,6 +387,7 @@ class const _TrackMap({
final (start, end) = (all.first, all.last); final (start, end) = (all.first, all.last);
return FlutterMap( return FlutterMap(
options: MapOptions( options: MapOptions(
maxZoom: mapMaxZoom,
initialCameraFit: all.length > 1 initialCameraFit: all.length > 1
? CameraFit.coordinates( ? CameraFit.coordinates(
coordinates: all, coordinates: all,

View file

@ -21,6 +21,7 @@ import 'package:halkyon_train_flutter/src/feature/loop/data/polar_loop.dart';
import 'package:halkyon_train_flutter/src/feature/loop/model/loop_figures.dart'; import 'package:halkyon_train_flutter/src/feature/loop/model/loop_figures.dart';
import 'package:halkyon_train_flutter/src/feature/map/data/map_source_repository.dart'; import 'package:halkyon_train_flutter/src/feature/map/data/map_source_repository.dart';
import 'package:halkyon_train_flutter/src/feature/map/data/offline_maps.dart'; import 'package:halkyon_train_flutter/src/feature/map/data/offline_maps.dart';
import 'package:halkyon_train_flutter/src/feature/map/widget/map_tiles.dart';
import 'package:halkyon_train_flutter/src/feature/music/data/recorder_music.dart'; import 'package:halkyon_train_flutter/src/feature/music/data/recorder_music.dart';
import 'package:halkyon_train_flutter/src/feature/plan/data/plan_repository.dart'; import 'package:halkyon_train_flutter/src/feature/plan/data/plan_repository.dart';
import 'package:halkyon_train_flutter/src/feature/plan/model/plan.dart'; import 'package:halkyon_train_flutter/src/feature/plan/model/plan.dart';
@ -2268,6 +2269,19 @@ void main() {
expect(find.textContaining('No way found there'), findsNothing); expect(find.textContaining('No way found there'), findsNothing);
}); });
testWidgets('the maps stop where their tiles stop being drawn', (
tester,
) async {
await openRoutes(tester);
await tester.tap(find.text('New route'));
await tester.pumpAndSettle();
expect(
tester.widget<FlutterMap>(find.byType(FlutterMap)).options.maxZoom,
mapMaxZoom,
);
});
testWidgets('an instance that plans no routes says so', (tester) async { testWidgets('an instance that plans no routes says so', (tester) async {
routing.isOffered = false; routing.isOffered = false;
await openRoutes(tester); await openRoutes(tester);
@ -2648,6 +2662,10 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.byType(FlutterMap), findsOneWidget); expect(find.byType(FlutterMap), findsOneWidget);
expect(
tester.widget<FlutterMap>(find.byType(FlutterMap)).options.maxZoom,
mapMaxZoom,
);
expect(find.text('2.50 km'), findsOneWidget); expect(find.text('2.50 km'), findsOneWidget);
expect(find.text('20 m'), findsOneWidget); expect(find.text('20 m'), findsOneWidget);
expect(find.text('whole time'), findsOneWidget); expect(find.text('whole time'), findsOneWidget);