This commit is contained in:
@@ -24,8 +24,13 @@ import '../domain/place_models.dart';
|
||||
import 'widgets/place_photo_card.dart';
|
||||
|
||||
String get _mapboxStyle {
|
||||
final style = runtime_config.mapboxStyle();
|
||||
return style.isEmpty ? 'mapbox/standard' : style;
|
||||
final style = runtime_config.mapboxStyle().trim();
|
||||
if (style.isEmpty ||
|
||||
style == 'mapbox/standard' ||
|
||||
style == mbx.MapboxStyles.STANDARD) {
|
||||
return mbx.MapboxStyles.STANDARD_SATELLITE;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
class MapflowShell extends StatelessWidget {
|
||||
@@ -67,6 +72,7 @@ class _MapContentState extends State<_MapContent> {
|
||||
final state = widget.state;
|
||||
final selected = state.selectedPlace;
|
||||
final userCoordinate = state.userCoordinate;
|
||||
final targetCenter = _focusCenter(state);
|
||||
final placeCubit = context.read<PlaceCubit>();
|
||||
final traitCounts = _countPlaceTraits(state.places);
|
||||
final availableTraits = [
|
||||
@@ -86,12 +92,13 @@ class _MapContentState extends State<_MapContent> {
|
||||
body: Stack(
|
||||
children: [
|
||||
_MapboxMapLayer(
|
||||
focusCenter: _focusCenter(state),
|
||||
focusCenter: targetCenter,
|
||||
places: state.recommendations,
|
||||
selectedPlaceId: selected?.id,
|
||||
userCoordinate: userCoordinate,
|
||||
onPlaceTap: (place) => _selectAndShowPlace(context, place),
|
||||
),
|
||||
if (targetCenter == null) const _MapTargetLoadingOverlay(),
|
||||
SafeArea(
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
@@ -323,7 +330,7 @@ class _MapboxMapLayer extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MapboxMapLayerState extends State<_MapboxMapLayer> {
|
||||
static const _worldCenter = LatLng(8.0, 32.0);
|
||||
static const _worldCenter = LatLng(0, 0);
|
||||
|
||||
mbx.MapboxMap? _mapboxMap;
|
||||
var _mapLoaded = false;
|
||||
@@ -351,8 +358,8 @@ class _MapboxMapLayerState extends State<_MapboxMapLayer> {
|
||||
styleUri: _mapboxStyleUri,
|
||||
viewport: mbx.CameraViewportState(
|
||||
center: _mapboxPoint(_worldCenter),
|
||||
zoom: 0.58,
|
||||
bearing: -42,
|
||||
zoom: 0.48,
|
||||
bearing: 0,
|
||||
pitch: 0,
|
||||
),
|
||||
onMapCreated: _onMapCreated,
|
||||
@@ -425,14 +432,14 @@ class _MapboxMapLayerState extends State<_MapboxMapLayer> {
|
||||
_lastFocusCenter = focusCenter;
|
||||
final camera = mbx.CameraOptions(
|
||||
center: _mapboxPoint(focusCenter),
|
||||
zoom: 14.8,
|
||||
bearing: -16,
|
||||
pitch: 62,
|
||||
zoom: 15.0,
|
||||
bearing: -12,
|
||||
pitch: 60,
|
||||
);
|
||||
if (_didInitialFlyIn) {
|
||||
_cameraAnimationSequence++;
|
||||
unawaited(
|
||||
mapboxMap.easeTo(camera, mbx.MapAnimationOptions(duration: 900)),
|
||||
mapboxMap.easeTo(camera, mbx.MapAnimationOptions(duration: 650)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -442,27 +449,36 @@ class _MapboxMapLayerState extends State<_MapboxMapLayer> {
|
||||
unawaited(
|
||||
mapboxMap.easeTo(
|
||||
mbx.CameraOptions(
|
||||
center: _mapboxPoint(_worldCenter),
|
||||
zoom: 0.62,
|
||||
bearing: 26,
|
||||
center: _mapboxPoint(_targetOrbitCenter(focusCenter)),
|
||||
zoom: 0.72,
|
||||
bearing: _targetOrbitBearing(focusCenter),
|
||||
pitch: 0,
|
||||
),
|
||||
mbx.MapAnimationOptions(duration: 1100),
|
||||
mbx.MapAnimationOptions(duration: 850),
|
||||
),
|
||||
);
|
||||
_initialFlyInTimer?.cancel();
|
||||
_initialFlyInTimer = Timer(const Duration(milliseconds: 760), () {
|
||||
_initialFlyInTimer = Timer(const Duration(milliseconds: 520), () {
|
||||
if (!mounted ||
|
||||
animationSequence != _cameraAnimationSequence ||
|
||||
_mapboxMap != mapboxMap) {
|
||||
return;
|
||||
}
|
||||
unawaited(
|
||||
mapboxMap.flyTo(camera, mbx.MapAnimationOptions(duration: 4600)),
|
||||
mapboxMap.flyTo(camera, mbx.MapAnimationOptions(duration: 2800)),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
LatLng _targetOrbitCenter(LatLng target) {
|
||||
final latitude = (target.latitude * 0.18).clamp(-18.0, 18.0);
|
||||
return LatLng(latitude, target.longitude);
|
||||
}
|
||||
|
||||
double _targetOrbitBearing(LatLng target) {
|
||||
return (-target.longitude * 0.34).clamp(-64.0, 64.0);
|
||||
}
|
||||
|
||||
Future<void> _projectMarkers() async {
|
||||
final mapboxMap = _mapboxMap;
|
||||
if (!_mapLoaded || mapboxMap == null) {
|
||||
@@ -1499,6 +1515,49 @@ class _MapLoading extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _MapTargetLoadingOverlay extends StatelessWidget {
|
||||
const _MapTargetLoadingOverlay();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final tokens = context.mapflowTokens;
|
||||
return IgnorePointer(
|
||||
child: SafeArea(
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 18),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: tokens.mapPanel.withValues(alpha: 0.84),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.24),
|
||||
blurRadius: 22,
|
||||
offset: const Offset(0, 10),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: SizedBox.square(
|
||||
dimension: 28,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2.5,
|
||||
color: tokens.voiceAccent,
|
||||
backgroundColor: tokens.onDark.withValues(alpha: 0.12),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _MapError extends StatelessWidget {
|
||||
const _MapError({required this.message});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user