map: improved default center

This commit is contained in:
Thibault Deckers 2022-09-03 15:25:50 +02:00
parent c5f8981a7e
commit 785e093e84
6 changed files with 52 additions and 20 deletions

View file

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:aves/l10n/l10n.dart';
@ -15,6 +16,7 @@ import 'package:aves_map/aves_map.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:latlong2/latlong.dart';
final Settings settings = Settings._private();
@ -121,11 +123,14 @@ class Settings extends ChangeNotifier {
static const subtitleBackgroundColorKey = 'subtitle_background_color';
// info
static const infoMapStyleKey = 'info_map_style';
static const infoMapZoomKey = 'info_map_zoom';
static const coordinateFormatKey = 'coordinates_format';
static const unitSystemKey = 'unit_system';
// map
static const mapStyleKey = 'info_map_style';
static const mapDefaultCenterKey = 'map_default_center';
// search
static const saveSearchHistoryKey = 'save_search_history';
static const searchHistoryKey = 'search_history';
@ -198,10 +203,10 @@ class Settings extends ChangeNotifier {
// availability
final defaultMapStyle = mobileServices.defaultMapStyle;
if (mobileServices.mapStyles.contains(defaultMapStyle)) {
infoMapStyle = defaultMapStyle;
mapStyle = defaultMapStyle;
} else {
final styles = EntryMapStyle.values.whereNot((v) => v.needMobileService).toList();
infoMapStyle = styles[Random().nextInt(styles.length)];
mapStyle = styles[Random().nextInt(styles.length)];
}
}
@ -556,14 +561,6 @@ class Settings extends ChangeNotifier {
// info
EntryMapStyle get infoMapStyle {
final preferred = getEnumOrDefault(infoMapStyleKey, SettingsDefaults.infoMapStyle, EntryMapStyle.values);
final available = availability.mapStyles;
return available.contains(preferred) ? preferred : available.first;
}
set infoMapStyle(EntryMapStyle newValue) => setAndNotify(infoMapStyleKey, newValue.toString());
double get infoMapZoom => getDouble(infoMapZoomKey) ?? SettingsDefaults.infoMapZoom;
set infoMapZoom(double newValue) => setAndNotify(infoMapZoomKey, newValue);
@ -576,6 +573,23 @@ class Settings extends ChangeNotifier {
set unitSystem(UnitSystem newValue) => setAndNotify(unitSystemKey, newValue.toString());
// map
EntryMapStyle get mapStyle {
final preferred = getEnumOrDefault(mapStyleKey, SettingsDefaults.infoMapStyle, EntryMapStyle.values);
final available = availability.mapStyles;
return available.contains(preferred) ? preferred : available.first;
}
set mapStyle(EntryMapStyle newValue) => setAndNotify(mapStyleKey, newValue.toString());
LatLng? get mapDefaultCenter {
final json = getString(mapDefaultCenterKey);
return json != null ? LatLng.fromJson(jsonDecode(json)) : null;
}
set mapDefaultCenter(LatLng? newValue) => setAndNotify(mapDefaultCenterKey, newValue != null ? jsonEncode(newValue.toJson()) : null);
// search
bool get saveSearchHistory => getBoolOrDefault(saveSearchHistoryKey, SettingsDefaults.saveSearchHistory);
@ -863,7 +877,8 @@ class Settings extends ChangeNotifier {
case videoLoopModeKey:
case videoControlsKey:
case subtitleTextAlignmentKey:
case infoMapStyleKey:
case mapStyleKey:
case mapDefaultCenterKey:
case coordinateFormatKey:
case unitSystemKey:
case accessibilityAnimationsKey:

View file

@ -129,11 +129,11 @@ class MapButtonPanel extends StatelessWidget {
onPressed: () => showSelectionDialog<EntryMapStyle>(
context: context,
builder: (context) => AvesSelectionDialog<EntryMapStyle>(
initialValue: settings.infoMapStyle,
initialValue: settings.mapStyle,
options: Map.fromEntries(availability.mapStyles.map((v) => MapEntry(v, v.getName(context)))),
title: context.l10n.mapStyleDialogTitle,
),
onSelection: (v) => settings.infoMapStyle = v,
onSelection: (v) => settings.mapStyle = v,
),
tooltip: context.l10n.mapStyleTooltip,
),

View file

@ -149,7 +149,7 @@ class _GeoMapState extends State<GeoMap> {
}
return Selector<Settings, EntryMapStyle>(
selector: (context, s) => s.infoMapStyle,
selector: (context, s) => s.mapStyle,
builder: (context, mapStyle, child) {
final isHeavy = mapStyle.isHeavy;
Widget _buildMarkerWidget(MarkerKey<AvesEntry> key) => ImageMarker(
@ -281,6 +281,7 @@ class _GeoMapState extends State<GeoMap> {
final overlayEntry = widget.overlayEntry;
if (overlayEntry != null) {
// fit map to overlaid item
final corner1 = overlayEntry.topLeft;
final corner2 = overlayEntry.bottomRight;
if (corner1 != null && corner2 != null) {
@ -290,10 +291,26 @@ class _GeoMapState extends State<GeoMap> {
}
}
if (bounds == null) {
// fit map to located items
final initialCenter = widget.initialCenter;
final points = initialCenter != null ? {initialCenter} : entries.map((v) => v.latLng!).toSet();
if (points.isNotEmpty) {
bounds = ZoomedBounds.fromPoints(
points: points,
collocationZoom: settings.infoMapZoom,
);
final center = bounds.projectedCenter;
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return;
settings.mapDefaultCenter = center;
});
}
}
if (bounds == null) {
// fallback to default center
final center = settings.mapDefaultCenter ??= Constants.wonders[Random().nextInt(Constants.wonders.length)];
bounds = ZoomedBounds.fromPoints(
points: points.isNotEmpty ? points : {Constants.wonders[Random().nextInt(Constants.wonders.length)]},
points: {center},
collocationZoom: settings.infoMapZoom,
);
}

View file

@ -78,7 +78,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
void initState() {
super.initState();
if (settings.infoMapStyle.isHeavy) {
if (settings.mapStyle.isHeavy) {
_isPageAnimatingNotifier = ValueNotifier(true);
Future.delayed(Durations.pageTransitionAnimation * timeDilation).then((_) {
if (!mounted) return;

View file

@ -107,7 +107,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
void initState() {
super.initState();
if (settings.infoMapStyle.isHeavy) {
if (settings.mapStyle.isHeavy) {
_isPageAnimatingNotifier.value = true;
Future.delayed(Durations.pageTransitionAnimation * timeDilation).then((_) {
if (!mounted) return;
@ -170,7 +170,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
return true;
},
child: Selector<Settings, EntryMapStyle>(
selector: (context, s) => s.infoMapStyle,
selector: (context, s) => s.mapStyle,
builder: (context, mapStyle, child) {
late Widget scroller;
if (mapStyle.isHeavy) {

View file

@ -38,6 +38,6 @@ Future<void> configureAndLaunch() async {
..showOverlayThumbnailPreview = true
..imageBackground = EntryBackground.checkered
// info
..infoMapStyle = EntryMapStyle.googleNormal;
..mapStyle = EntryMapStyle.googleNormal;
app.main();
}