From 68f2fe54f1c62f6f676ebb87db78374ba0f6a135 Mon Sep 17 00:00:00 2001 From: Jam Hernandez Quiceno Date: Mon, 2 Feb 2026 17:11:00 -0500 Subject: [PATCH] Mabox v3 support. Support Flutter argument("limit").longValue()); break; + case "setHttpHeaders": Map headers = (Map) methodCall.argument("headers"); MapboxHttpRequestUtil.setHttpHeaders(headers, result); break; + case "downloadOfflineRegion": - // Get args from caller Map definitionMap = (Map) methodCall.argument("definition"); Map metadataMap = (Map) methodCall.argument("metadata"); String channelName = methodCall.argument("channelName"); - // Prepare args OfflineChannelHandlerImpl channelHandler = new OfflineChannelHandlerImpl(messenger, channelName); - // Start downloading - OfflineManagerUtils.downloadRegion( - result, context, definitionMap, metadataMap, channelHandler); + OfflineManagerUtils.downloadRegion(result, context, definitionMap, metadataMap, channelHandler); break; + case "getListOfRegions": OfflineManagerUtils.regionsList(result, context); break; + case "updateOfflineRegionMetadata": - // Get download region arguments from caller Map metadata = (Map) methodCall.argument("metadata"); OfflineManagerUtils.updateRegionMetadata( result, context, methodCall.argument("id").longValue(), metadata); break; + case "deleteOfflineRegion": - OfflineManagerUtils.deleteRegion( - result, context, methodCall.argument("id").longValue()); + OfflineManagerUtils.deleteRegion(result, context, methodCall.argument("id").longValue()); break; + default: result.notImplemented(); break; @@ -138,17 +141,13 @@ private void installOfflineMapTiles(String tilesDb) { } private InputStream openTilesDbFile(String tilesDb) throws IOException { + if (tilesDb == null) throw new IllegalArgumentException("tilesdb is null"); + if (tilesDb.startsWith("/")) { // Absolute path. return new FileInputStream(new File(tilesDb)); } else { - String assetKey; - if (registrar != null) { - assetKey = registrar.lookupKeyForAsset(tilesDb); - } else if (flutterAssets != null) { - assetKey = flutterAssets.getAssetFilePathByName(tilesDb); - } else { - throw new IllegalStateException(); - } + // Flutter embedding v2 asset lookup + String assetKey = flutterAssets.getAssetFilePathByName(tilesDb); return context.getAssets().open(assetKey); } } diff --git a/android/src/main/java/com/mapbox/mapboxgl/MapboxMapsPlugin.java b/android/src/main/java/com/mapbox/mapboxgl/MapboxMapsPlugin.java index 3f25d26a6..3145b90fc 100644 --- a/android/src/main/java/com/mapbox/mapboxgl/MapboxMapsPlugin.java +++ b/android/src/main/java/com/mapbox/mapboxgl/MapboxMapsPlugin.java @@ -1,23 +1,13 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - package com.mapbox.mapboxgl; -import android.app.Activity; -import android.app.Application; -import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.lifecycle.Lifecycle; -import androidx.lifecycle.LifecycleOwner; -import androidx.lifecycle.LifecycleRegistry; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference; import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.PluginRegistry.Registrar; /** * Plugin for controlling a set of MapboxMap views to be shown as overlays on top of the Flutter @@ -28,28 +18,28 @@ public class MapboxMapsPlugin implements FlutterPlugin, ActivityAware { private static final String VIEW_TYPE = "plugins.flutter.io/mapbox_gl"; + private static final String CHANNEL_NAME = "plugins.flutter.io/mapbox_gl"; static FlutterAssets flutterAssets; - private Lifecycle lifecycle; + + @Nullable private Lifecycle lifecycle; + @Nullable private MethodChannel methodChannel; public MapboxMapsPlugin() { // no-op } - // New Plugin APIs - @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { flutterAssets = binding.getFlutterAssets(); - MethodChannel methodChannel = - new MethodChannel(binding.getBinaryMessenger(), "plugins.flutter.io/mapbox_gl"); + methodChannel = new MethodChannel(binding.getBinaryMessenger(), CHANNEL_NAME); methodChannel.setMethodCallHandler(new GlobalMethodHandler(binding)); binding .getPlatformViewRegistry() .registerViewFactory( - "plugins.flutter.io/mapbox_gl", + VIEW_TYPE, new MapboxMapFactory( binding.getBinaryMessenger(), new LifecycleProvider() { @@ -63,7 +53,11 @@ public Lifecycle getLifecycle() { @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - // no-op + if (methodChannel != null) { + methodChannel.setMethodCallHandler(null); + methodChannel = null; + } + // flutterAssets is static; leave as-is or null it if you prefer. } @Override @@ -86,111 +80,6 @@ public void onDetachedFromActivity() { lifecycle = null; } - // Old Plugin APIs - - public static void registerWith(Registrar registrar) { - final Activity activity = registrar.activity(); - if (activity == null) { - // When a background flutter view tries to register the plugin, the registrar has no activity. - // We stop the registration process as this plugin is foreground only. - return; - } - if (activity instanceof LifecycleOwner) { - registrar - .platformViewRegistry() - .registerViewFactory( - VIEW_TYPE, - new MapboxMapFactory( - registrar.messenger(), - new LifecycleProvider() { - @Override - public Lifecycle getLifecycle() { - return ((LifecycleOwner) activity).getLifecycle(); - } - })); - } else { - registrar - .platformViewRegistry() - .registerViewFactory( - VIEW_TYPE, - new MapboxMapFactory(registrar.messenger(), new ProxyLifecycleProvider(activity))); - } - - MethodChannel methodChannel = - new MethodChannel(registrar.messenger(), "plugins.flutter.io/mapbox_gl"); - methodChannel.setMethodCallHandler(new GlobalMethodHandler(registrar)); - } - - private static final class ProxyLifecycleProvider - implements Application.ActivityLifecycleCallbacks, LifecycleOwner, LifecycleProvider { - - private final LifecycleRegistry lifecycle = new LifecycleRegistry(this); - private final int registrarActivityHashCode; - - private ProxyLifecycleProvider(Activity activity) { - this.registrarActivityHashCode = activity.hashCode(); - activity.getApplication().registerActivityLifecycleCallbacks(this); - } - - @Override - public void onActivityCreated(Activity activity, Bundle savedInstanceState) { - if (activity.hashCode() != registrarActivityHashCode) { - return; - } - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); - } - - @Override - public void onActivityStarted(Activity activity) { - if (activity.hashCode() != registrarActivityHashCode) { - return; - } - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START); - } - - @Override - public void onActivityResumed(Activity activity) { - if (activity.hashCode() != registrarActivityHashCode) { - return; - } - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME); - } - - @Override - public void onActivityPaused(Activity activity) { - if (activity.hashCode() != registrarActivityHashCode) { - return; - } - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE); - } - - @Override - public void onActivityStopped(Activity activity) { - if (activity.hashCode() != registrarActivityHashCode) { - return; - } - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP); - } - - @Override - public void onActivitySaveInstanceState(Activity activity, Bundle outState) {} - - @Override - public void onActivityDestroyed(Activity activity) { - if (activity.hashCode() != registrarActivityHashCode) { - return; - } - activity.getApplication().unregisterActivityLifecycleCallbacks(this); - lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY); - } - - @NonNull - @Override - public Lifecycle getLifecycle() { - return lifecycle; - } - } - interface LifecycleProvider { @Nullable Lifecycle getLifecycle(); @@ -202,12 +91,11 @@ public static class FlutterLifecycleAdapter { /** * Returns the lifecycle object for the activity a plugin is bound to. * - *

Returns null if the Flutter engine version does not include the lifecycle extraction code. + *

Returns null if the Flutter engine version does not include the lifecycle extraction code * (this probably means the Flutter engine version is too old). */ @NonNull - public static Lifecycle getActivityLifecycle( - @NonNull ActivityPluginBinding activityPluginBinding) { + public static Lifecycle getActivityLifecycle(@NonNull ActivityPluginBinding activityPluginBinding) { HiddenLifecycleReference reference = (HiddenLifecycleReference) activityPluginBinding.getLifecycle(); return reference.getLifecycle(); diff --git a/lib/mapbox_gl.dart b/lib/mapbox_gl.dart index ea45970d3..8a18dbf73 100644 --- a/lib/mapbox_gl.dart +++ b/lib/mapbox_gl.dart @@ -48,7 +48,8 @@ export 'package:mapbox_gl_platform_interface/mapbox_gl_platform_interface.dart' RasterDemSourceProperties, GeojsonSourceProperties, VideoSourceProperties, - ImageSourceProperties; + ImageSourceProperties, + TerrainProperties; part 'src/controller.dart'; part 'src/mapbox_map.dart'; diff --git a/lib/src/controller.dart b/lib/src/controller.dart index e70e06a27..609750bbf 100644 --- a/lib/src/controller.dart +++ b/lib/src/controller.dart @@ -323,10 +323,10 @@ class MapboxMapController extends ChangeNotifier { /// platform side. /// Future addGeoJsonSource(String sourceId, Map geojson, - {String? promoteId}) async { + {String? promoteId, bool enableLineMetrics = false}) async { _disposeGuard(); await _mapboxGlPlatform.addGeoJsonSource(sourceId, geojson, - promoteId: promoteId); + promoteId: promoteId, enableLineMetrics: enableLineMetrics); } /// Sets new geojson data to and existing source @@ -1296,6 +1296,11 @@ class MapboxMapController extends ChangeNotifier { return _mapboxGlPlatform.addSource(sourceid, properties); } + Future setTerrain(TerrainProperties properties) async { + _disposeGuard(); + return _mapboxGlPlatform.setTerrain(properties); + } + /// Add a layer to the map with the given properties /// /// The returned [Future] completes after the change has been made on the diff --git a/lib/src/layer_properties.dart b/lib/src/layer_properties.dart index 8624c23d9..19d5d712e 100644 --- a/lib/src/layer_properties.dart +++ b/lib/src/layer_properties.dart @@ -780,6 +780,9 @@ class SymbolLayerProperties implements LayerProperties { /// basic functionality with js, android, ios, macos final dynamic visibility; + final dynamic symbolZOffset; + final dynamic symbolElevationReference; + const SymbolLayerProperties({ this.iconOpacity, this.iconColor, @@ -800,6 +803,8 @@ class SymbolLayerProperties implements LayerProperties { this.symbolAvoidEdges, this.symbolSortKey, this.symbolZOrder, + this.symbolZOffset, + this.symbolElevationReference, this.iconAllowOverlap, this.iconIgnorePlacement, this.iconOptional, @@ -860,6 +865,9 @@ class SymbolLayerProperties implements LayerProperties { symbolAvoidEdges: changes.symbolAvoidEdges ?? symbolAvoidEdges, symbolSortKey: changes.symbolSortKey ?? symbolSortKey, symbolZOrder: changes.symbolZOrder ?? symbolZOrder, + symbolZOffset: changes.symbolZOffset ?? symbolZOffset, + symbolElevationReference: + changes.symbolElevationReference ?? symbolElevationReference, iconAllowOverlap: changes.iconAllowOverlap ?? iconAllowOverlap, iconIgnorePlacement: changes.iconIgnorePlacement ?? iconIgnorePlacement, iconOptional: changes.iconOptional ?? iconOptional, @@ -930,6 +938,8 @@ class SymbolLayerProperties implements LayerProperties { addIfPresent('symbol-avoid-edges', symbolAvoidEdges); addIfPresent('symbol-sort-key', symbolSortKey); addIfPresent('symbol-z-order', symbolZOrder); + addIfPresent('symbol-z-offset', symbolZOffset); + addIfPresent('symbol-elevation-reference', symbolElevationReference); addIfPresent('icon-allow-overlap', iconAllowOverlap); addIfPresent('icon-ignore-placement', iconIgnorePlacement); addIfPresent('icon-optional', iconOptional); @@ -991,6 +1001,8 @@ class SymbolLayerProperties implements LayerProperties { symbolAvoidEdges: json['symbol-avoid-edges'], symbolSortKey: json['symbol-sort-key'], symbolZOrder: json['symbol-z-order'], + symbolZOffset: json['symbol-z-offset'], + symbolElevationReference: json['symbol-elevation-reference'], iconAllowOverlap: json['icon-allow-overlap'], iconIgnorePlacement: json['icon-ignore-placement'], iconOptional: json['icon-optional'], @@ -1487,6 +1499,10 @@ class LineLayerProperties implements LayerProperties { /// basic functionality with js, android, ios, macos final dynamic visibility; + final dynamic lineZOffset; + final dynamic lineElevationReference; + final dynamic lineEmissiveStrength; + const LineLayerProperties({ this.lineOpacity, this.lineColor, @@ -1499,6 +1515,9 @@ class LineLayerProperties implements LayerProperties { this.lineDasharray, this.linePattern, this.lineGradient, + this.lineZOffset, + this.lineElevationReference, + this.lineEmissiveStrength, this.lineCap, this.lineJoin, this.lineMiterLimit, @@ -1520,6 +1539,11 @@ class LineLayerProperties implements LayerProperties { lineDasharray: changes.lineDasharray ?? lineDasharray, linePattern: changes.linePattern ?? linePattern, lineGradient: changes.lineGradient ?? lineGradient, + lineZOffset: changes.lineZOffset ?? lineZOffset, + lineElevationReference: + changes.lineElevationReference ?? lineElevationReference, + lineEmissiveStrength: + changes.lineEmissiveStrength ?? lineEmissiveStrength, lineCap: changes.lineCap ?? lineCap, lineJoin: changes.lineJoin ?? lineJoin, lineMiterLimit: changes.lineMiterLimit ?? lineMiterLimit, @@ -1555,6 +1579,9 @@ class LineLayerProperties implements LayerProperties { addIfPresent('line-round-limit', lineRoundLimit); addIfPresent('line-sort-key', lineSortKey); addIfPresent('visibility', visibility); + addIfPresent('line-z-offset', lineZOffset); + addIfPresent('line-elevation-reference', lineElevationReference); + addIfPresent('line-emissive-strength', lineEmissiveStrength); return json; } @@ -1571,6 +1598,9 @@ class LineLayerProperties implements LayerProperties { lineDasharray: json['line-dasharray'], linePattern: json['line-pattern'], lineGradient: json['line-gradient'], + lineZOffset: json['line-z-offset'], + lineElevationReference: json['line-elevation-reference'], + lineEmissiveStrength: json['line-emissive-strength'], lineCap: json['line-cap'], lineJoin: json['line-join'], lineMiterLimit: json['line-miter-limit'], diff --git a/lib/src/mapbox_map.dart b/lib/src/mapbox_map.dart index 6649c8c24..1fd873d66 100644 --- a/lib/src/mapbox_map.dart +++ b/lib/src/mapbox_map.dart @@ -43,6 +43,8 @@ class MapboxMap extends StatefulWidget { this.onCameraTrackingChanged, this.onCameraIdle, this.onMapIdle, + this.minPitch = 0, + this.maxPitch = 85, this.annotationOrder = const [ AnnotationType.line, AnnotationType.symbol, @@ -125,6 +127,9 @@ class MapboxMap extends StatefulWidget { /// True if the map view should respond to tilt gestures. final bool tiltGesturesEnabled; + final double minPitch; + final double maxPitch; + /// Set to true to forcefully disable/enable if map should respond to double /// click to zoom. /// @@ -255,6 +260,7 @@ class _MapboxMapState extends State { assert( widget.annotationOrder.toSet().length == widget.annotationOrder.length, "annotationOrder must not have duplicate types"); + print(_MapboxMapOptions.fromWidget(widget).toMap()); final Map creationParams = { 'initialCameraPosition': widget.initialCameraPosition.toMap(), 'options': _MapboxMapOptions.fromWidget(widget).toMap(), @@ -262,6 +268,9 @@ class _MapboxMapState extends State { 'onAttributionClickOverride': widget.onAttributionClick != null, 'dragEnabled': widget.dragEnabled, 'useHybridCompositionOverride': widget.useHybridCompositionOverride, + 'minPitch': widget.minPitch, + 'maxPitch': widget.maxPitch, + 'style': widget.styleString }; return _mapboxGlPlatform.buildView( creationParams, onPlatformViewCreated, widget.gestureRecognizers); @@ -354,6 +363,8 @@ class _MapboxMapOptions { this.compassViewMargins, this.attributionButtonPosition, this.attributionButtonMargins, + this.minPitch, + this.maxPitch, }); static _MapboxMapOptions fromWidget(MapboxMap map) { @@ -377,9 +388,14 @@ class _MapboxMapOptions { compassViewMargins: map.compassViewMargins, attributionButtonPosition: map.attributionButtonPosition, attributionButtonMargins: map.attributionButtonMargins, + minPitch: map.minPitch, + maxPitch: map.maxPitch, ); } + final double? minPitch; + final double? maxPitch; + final bool? compassEnabled; final CameraTargetBounds? cameraTargetBounds; @@ -452,6 +468,9 @@ class _MapboxMapOptions { addIfNonNull('zoomGesturesEnabled', zoomGesturesEnabled); addIfNonNull('doubleClickZoomEnabled', doubleClickZoomEnabled); + addIfNonNull('maxPitch', maxPitch); + addIfNonNull('minPitch', minPitch); + addIfNonNull('trackCameraPosition', trackCameraPosition); addIfNonNull('myLocationEnabled', myLocationEnabled); addIfNonNull('myLocationTrackingMode', myLocationTrackingMode?.index); @@ -462,6 +481,8 @@ class _MapboxMapOptions { addIfNonNull('attributionButtonPosition', attributionButtonPosition?.index); addIfNonNull( 'attributionButtonMargins', pointToArray(attributionButtonMargins)); + optionsMap["pitch"] = 20; + optionsMap["bearing"] = -60; return optionsMap; } diff --git a/mapbox_gl_platform_interface/lib/src/camera.dart b/mapbox_gl_platform_interface/lib/src/camera.dart index 3094923aa..0c49e3371 100644 --- a/mapbox_gl_platform_interface/lib/src/camera.dart +++ b/mapbox_gl_platform_interface/lib/src/camera.dart @@ -80,7 +80,7 @@ class CameraPosition { } @override - int get hashCode => hashValues(bearing, target, tilt, zoom); + int get hashCode => Object.hash(bearing, target, tilt, zoom); @override String toString() => diff --git a/mapbox_gl_platform_interface/lib/src/location.dart b/mapbox_gl_platform_interface/lib/src/location.dart index 7c058dda9..879cd74cf 100644 --- a/mapbox_gl_platform_interface/lib/src/location.dart +++ b/mapbox_gl_platform_interface/lib/src/location.dart @@ -53,7 +53,7 @@ class LatLng { } @override - int get hashCode => hashValues(latitude, longitude); + int get hashCode => Object.hash(latitude, longitude); } /// A latitude/longitude aligned rectangle. @@ -106,7 +106,7 @@ class LatLngBounds { } @override - int get hashCode => hashValues(southwest, northeast); + int get hashCode => Object.hash(southwest, northeast); } /// A geographical area representing a non-aligned quadrilateral @@ -164,7 +164,7 @@ class LatLngQuad { } @override - int get hashCode => hashValues(topLeft, topRight, bottomRight, bottomLeft); + int get hashCode => Object.hash(topLeft, topRight, bottomRight, bottomLeft); } /// User's observed location diff --git a/mapbox_gl_platform_interface/lib/src/mapbox_gl_platform_interface.dart b/mapbox_gl_platform_interface/lib/src/mapbox_gl_platform_interface.dart index 346998bd0..2bf0c0aa1 100644 --- a/mapbox_gl_platform_interface/lib/src/mapbox_gl_platform_interface.dart +++ b/mapbox_gl_platform_interface/lib/src/mapbox_gl_platform_interface.dart @@ -105,7 +105,7 @@ abstract class MapboxGlPlatform { Future getMetersPerPixelAtLatitude(double latitude); Future addGeoJsonSource(String sourceId, Map geojson, - {String? promoteId}); + {String? promoteId, bool enableLineMetrics = false}); Future setGeoJsonSource(String sourceId, Map geojson); @@ -181,6 +181,7 @@ abstract class MapboxGlPlatform { double? maxzoom}); Future addSource(String sourceId, SourceProperties properties); + Future setTerrain(TerrainProperties properties); Future takeSnapshot(SnapshotOptions snapshotOptions); diff --git a/mapbox_gl_platform_interface/lib/src/method_channel_mapbox_gl.dart b/mapbox_gl_platform_interface/lib/src/method_channel_mapbox_gl.dart index 2187f21c8..c91abf787 100644 --- a/mapbox_gl_platform_interface/lib/src/method_channel_mapbox_gl.dart +++ b/mapbox_gl_platform_interface/lib/src/method_channel_mapbox_gl.dart @@ -548,7 +548,7 @@ class MethodChannelMapboxGl extends MapboxGlPlatform { @override Future addGeoJsonSource(String sourceId, Map geojson, - {String? promoteId}) async { + {String? promoteId, bool enableLineMetrics = false}) async { await _channel.invokeMethod('source#addGeoJson', { 'sourceId': sourceId, 'geojson': jsonEncode(geojson), @@ -772,4 +772,10 @@ class MethodChannelMapboxGl extends MapboxGlPlatform { return new Future.error(e); } } + + @override + Future setTerrain(TerrainProperties properties) { + // TODO: implement setTerrain + throw UnimplementedError(); + } } diff --git a/mapbox_gl_platform_interface/lib/src/source_properties.dart b/mapbox_gl_platform_interface/lib/src/source_properties.dart index c6b450c7c..cff1eb8ca 100644 --- a/mapbox_gl_platform_interface/lib/src/source_properties.dart +++ b/mapbox_gl_platform_interface/lib/src/source_properties.dart @@ -7,6 +7,30 @@ abstract class SourceProperties { Map toJson(); } +class TerrainProperties implements SourceProperties { + final String source; + final double? exaggeration; + + const TerrainProperties({ + required this.source, + this.exaggeration, + }); + + Map toJson() { + final Map json = {}; + + void addIfPresent(String fieldName, dynamic value) { + if (value != null) { + json[fieldName] = value; + } + } + + addIfPresent('source', source); + addIfPresent('exaggeration', exaggeration); + return json; + } +} + class VectorSourceProperties implements SourceProperties { /// A URL to a TileJSON resource. Supported protocols are `http:`, /// `https:`, and `mapbox://`. diff --git a/mapbox_gl_platform_interface/lib/src/ui.dart b/mapbox_gl_platform_interface/lib/src/ui.dart index 5bacf8a08..a7a11d4e6 100644 --- a/mapbox_gl_platform_interface/lib/src/ui.dart +++ b/mapbox_gl_platform_interface/lib/src/ui.dart @@ -5,32 +5,37 @@ part of mapbox_gl_platform_interface; class MapboxStyles { - static const String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v11"; + static const String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v12"; /// Outdoors: A general-purpose style tailored to outdoor activities. Using this constant means /// your map style will always use the latest version and may change as we improve the style. - static const String OUTDOORS = "mapbox://styles/mapbox/outdoors-v11"; + static const String OUTDOORS = "mapbox://styles/mapbox/outdoors-v12"; /// Light: Subtle light backdrop for data visualizations. Using this constant means your map /// style will always use the latest version and may change as we improve the style. - static const String LIGHT = "mapbox://styles/mapbox/light-v10"; + static const String LIGHT = "mapbox://styles/mapbox/light-v11"; /// Empty: Basic empty style static const String EMPTY = "mapbox://styles/mapbox/empty-v8"; /// Dark: Subtle dark backdrop for data visualizations. Using this constant means your map style /// will always use the latest version and may change as we improve the style. - static const String DARK = "mapbox://styles/mapbox/dark-v10"; + static const String DARK = "mapbox://styles/mapbox/dark-v11"; + + static const String STANDARD = "mapbox://styles/mapbox/standard"; /// Satellite: A beautiful global satellite and aerial imagery layer. Using this constant means /// your map style will always use the latest version and may change as we improve the style. static const String SATELLITE = "mapbox://styles/mapbox/satellite-v9"; + static const String STANDARD_SAT = + "mapbox://styles/mapbox/standard-satellite"; + /// Satellite Streets: Global satellite and aerial imagery with unobtrusive labels. Using this /// constant means your map style will always use the latest version and may change as we /// improve the style. static const String SATELLITE_STREETS = - "mapbox://styles/mapbox/satellite-streets-v11"; + "mapbox://styles/mapbox/satellite-streets-v12"; /// Traffic Day: Color-coded roads based on live traffic congestion data. Traffic data is currently /// available in @@ -143,7 +148,7 @@ class MinMaxZoomPreference { } @override - int get hashCode => hashValues(minZoom, maxZoom); + int get hashCode => Object.hash(minZoom, maxZoom); @override String toString() { diff --git a/mapbox_gl_platform_interface/pubspec.yaml b/mapbox_gl_platform_interface/pubspec.yaml index c3eae26be..2d31910c7 100644 --- a/mapbox_gl_platform_interface/pubspec.yaml +++ b/mapbox_gl_platform_interface/pubspec.yaml @@ -9,5 +9,5 @@ dependencies: meta: ^1.0.5 environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.12.0 <4.0.0' flutter: ">=2.0.0" diff --git a/mapbox_gl_web/lib/mapbox_gl_web.dart b/mapbox_gl_web/lib/mapbox_gl_web.dart index 0c154a4e6..29ecbf716 100644 --- a/mapbox_gl_web/lib/mapbox_gl_web.dart +++ b/mapbox_gl_web/lib/mapbox_gl_web.dart @@ -7,22 +7,21 @@ import 'dart:convert'; import 'dart:html'; // ignore: unused_import import 'dart:js'; -import 'dart:js_util'; +import 'dart:js_interop'; import 'dart:math'; import 'dart:typed_data'; -import 'dart:ui' as ui; +import 'dart:ui_web' as ui; import 'package:flutter/services.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart' hide Element; +import 'package:flutter/material.dart' hide Element, Image; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:mapbox_gl_platform_interface/mapbox_gl_platform_interface.dart'; import 'package:mapbox_gl_dart/mapbox_gl_dart.dart' hide Point, Source; import 'package:mapbox_gl_dart/mapbox_gl_dart.dart' as mapbox show Point; import 'package:image/image.dart' hide Point; -import 'package:js/js_util.dart' as jsUtil; import 'package:mapbox_gl_web/src/layer_tools.dart'; part 'src/convert.dart'; diff --git a/mapbox_gl_web/lib/src/layer_tools.dart b/mapbox_gl_web/lib/src/layer_tools.dart index b6564111b..5734963fa 100644 --- a/mapbox_gl_web/lib/src/layer_tools.dart +++ b/mapbox_gl_web/lib/src/layer_tools.dart @@ -7,6 +7,7 @@ const _layoutProperties = { "symbol-avoid-edges", "symbol-sort-key", "symbol-z-order", + "symbol-elevation-reference", "icon-allow-overlap", "icon-ignore-placement", "icon-optional", @@ -51,6 +52,8 @@ const _layoutProperties = { "line-round-limit", "line-sort-key", "fill-sort-key", + "line-z-offset", + 'line-elevation-reference', }; bool isLayoutProperty(String property) { diff --git a/mapbox_gl_web/lib/src/mapbox_web_gl_platform.dart b/mapbox_gl_web/lib/src/mapbox_web_gl_platform.dart index f1868cace..fc09ab5ae 100644 --- a/mapbox_gl_web/lib/src/mapbox_web_gl_platform.dart +++ b/mapbox_gl_web/lib/src/mapbox_web_gl_platform.dart @@ -1,7 +1,7 @@ part of mapbox_gl_web; const _mapboxGlCssUrl = - 'https://api.mapbox.com/mapbox-gl-js/v2.7.0/mapbox-gl.css'; + "https://api.mapbox.com/mapbox-gl-js/v3.10.0/mapbox-gl.css"; class MapboxWebGlPlatform extends MapboxGlPlatform implements MapboxMapOptionsSink { @@ -71,12 +71,15 @@ class MapboxWebGlPlatform extends MapboxGlPlatform _map = MapboxMap( MapOptions( container: _mapElement, - style: 'mapbox://styles/mapbox/streets-v11', + style: + _creationParams["style"] ?? 'mapbox://styles/mapbox/streets-v11', center: LngLat(camera['target'][1], camera['target'][0]), zoom: camera['zoom'], bearing: camera['bearing'], pitch: camera['tilt'], preserveDrawingBuffer: true, + minPitch: _creationParams["minPitch"], + maxPitch: _creationParams["maxPitch"], ), ); _map.on('load', _onStyleLoaded); @@ -200,11 +203,11 @@ class MapboxWebGlPlatform extends MapboxGlPlatform {Duration? duration}) async { final cameraOptions = Convert.toCameraOptions(cameraUpdate, _map).jsObject; - final around = jsify(cameraOptions.around); - final bearing = jsify(cameraOptions.bearing); - final center = jsify(cameraOptions.center); - final pitch = jsify(cameraOptions.pitch); - final zoom = jsify(cameraOptions.zoom); + final around = cameraOptions.around.jsify(); + final bearing = cameraOptions.bearing.jsify(); + final center = cameraOptions.center.jsify(); + final pitch = cameraOptions.pitch.jsify(); + final zoom = cameraOptions.zoom.jsify(); _map.flyTo({ if (around != null) 'around': around, @@ -232,9 +235,7 @@ class MapboxWebGlPlatform extends MapboxGlPlatform } @override - Future matchMapLanguageWithDeviceDefault() async { - setMapLanguage(ui.window.locale.languageCode); - } + Future matchMapLanguageWithDeviceDefault() async {} @override Future setMapLanguage(String language) async { @@ -341,14 +342,22 @@ class MapboxWebGlPlatform extends MapboxGlPlatform @override Future addImage(String name, Uint8List bytes, [bool sdf = false]) async { - final photo = decodeImage(bytes)!; + final photo = decodeImage(bytes)!.convert(format: Format.uint8); + + late Image imageToLoad; + if (photo.format != Format.uint8) { + imageToLoad = photo.convert(format: Format.uint8); + } else { + imageToLoad = photo; + } + if (!_map.hasImage(name)) { _map.addImage( name, { - 'width': photo.width, - 'height': photo.height, - 'data': photo.getBytes(), + 'width': imageToLoad.width, + 'height': imageToLoad.height, + 'data': imageToLoad.toUint8List() }, {'sdf': sdf}, ); @@ -524,8 +533,8 @@ class MapboxWebGlPlatform extends MapboxGlPlatform _removeNavigationControl(); _navigationControl = NavigationControl(NavigationControlOptions( showCompass: newShowComapss, - showZoom: false, - visualizePitch: false, + showZoom: true, + visualizePitch: true, )); if (newPosition == null) { @@ -644,7 +653,7 @@ class MapboxWebGlPlatform extends MapboxGlPlatform try { final styleJson = jsonDecode(styleString ?? ''); - final styleJsObject = jsUtil.jsify(styleJson); + final styleJsObject = styleJson.jsify(); _map.setStyle(styleJsObject); } catch (_) { _map.setStyle(styleString); @@ -715,12 +724,13 @@ class MapboxWebGlPlatform extends MapboxGlPlatform @override Future addGeoJsonSource(String sourceId, Map geojson, - {String? promoteId}) async { + {String? promoteId, bool enableLineMetrics = false}) async { final data = _makeFeatureCollection(geojson); _addedFeaturesByLayer[sourceId] = data; _map.addSource(sourceId, { "type": 'geojson', "data": geojson, // pass the raw string here to avoid errors + if (enableLineMetrics) "lineMetrics": true, if (promoteId != null) "promoteId": promoteId }); } @@ -991,6 +1001,11 @@ class MapboxWebGlPlatform extends MapboxGlPlatform _map.addSource(sourceId, source.toJson()); } + @override + Future setTerrain(TerrainProperties properties) async { + _map.setTerrain(properties.toJson()); + } + Future addImageSource( String imageSourceId, Uint8List bytes, LatLngQuad coordinates) { // TODO: implement addImageSource diff --git a/mapbox_gl_web/pubspec.yaml b/mapbox_gl_web/pubspec.yaml index d14051e77..c3480bc7a 100644 --- a/mapbox_gl_web/pubspec.yaml +++ b/mapbox_gl_web/pubspec.yaml @@ -18,11 +18,17 @@ dependencies: meta: ^1.1.7 mapbox_gl_platform_interface: git: - url: https://github.com/tobrun/flutter-mapbox-gl.git + url: https://github.com/HiddenLevel/maps.git path: mapbox_gl_platform_interface - mapbox_gl_dart: ^0.2.1 + ref: feature/web-mapbox-v3-support + mapbox_gl_dart: + git: + url: https://github.com/HiddenLevel/mapbox-gl-dart.git + ref: feature/support-set-terrain image: '>=3.0.0 <5.0.0' + + dependency_overrides: mapbox_gl_platform_interface: path: ../mapbox_gl_platform_interface @@ -32,5 +38,5 @@ dev_dependencies: sdk: flutter environment: - sdk: ">=2.12.0 <3.0.0" + sdk: '>=2.12.0 <4.0.0' flutter: ">=2.0.0" diff --git a/pubspec.lock b/pubspec.lock index 3064bfbed..3ae7cf643 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,18 +13,18 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" collection: dependency: "direct main" description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.18.0" crypto: dependency: transitive description: @@ -55,10 +55,10 @@ packages: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" mapbox_gl_dart: dependency: transitive description: @@ -85,18 +85,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.12.0" path: dependency: transitive description: @@ -134,6 +134,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: "direct main" + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" xml: dependency: transitive description: @@ -143,5 +151,5 @@ packages: source: hosted version: "5.1.0" sdks: - dart: ">=2.17.0-0 <3.0.0" + dart: ">=3.4.0 <4.0.0" flutter: ">=2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index ea086f30b..c5db72a5a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,19 +1,24 @@ name: mapbox_gl description: A Flutter plugin for integrating Mapbox Maps inside a Flutter application on Android, iOS and web platfroms. version: 0.16.0 -homepage: https://github.com/tobrun/flutter-mapbox-gl +homepage: https://github.com/HiddenLevel/maps +publish_to: none dependencies: flutter: sdk: flutter mapbox_gl_platform_interface: git: - url: https://github.com/tobrun/flutter-mapbox-gl.git + url: https://github.com/HiddenLevel/maps.git path: mapbox_gl_platform_interface + ref: feature/web-mapbox-v3-support + mapbox_gl_web: git: - url: https://github.com/tobrun/flutter-mapbox-gl.git + url: https://github.com/HiddenLevel/maps.git path: mapbox_gl_web + ref: feature/web-mapbox-v3-support + collection: ^1.15.0 dependency_overrides: @@ -34,6 +39,5 @@ flutter: default_package: mapbox_gl_web environment: - sdk: '>=2.12.0 <3.0.0' - # Flutter versions prior to 1.10 did not support the flutter.plugin.platforms map. + sdk: '>=2.12.0 <4.0.0' flutter: ">=2.0.0" diff --git a/scripts/pubspec.lock b/scripts/pubspec.lock index fed710049..561dc45be 100644 --- a/scripts/pubspec.lock +++ b/scripts/pubspec.lock @@ -5,15 +5,17 @@ packages: dependency: "direct main" description: name: mustache_template - url: "https://pub.dartlang.org" + sha256: a46e26f91445bfb0b60519be280555b06792460b27b19e2b19ad5b9740df5d1c + url: "https://pub.dev" source: hosted version: "2.0.0" recase: dependency: "direct main" description: name: recase - url: "https://pub.dartlang.org" + sha256: "7aec9b9f498cba65ed969eda51ea3d86a77bbd633d876b57d9db7d9f94fc6ca5" + url: "https://pub.dev" source: hosted version: "4.0.0" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=2.12.0 <4.0.0"