Skip to content

Commit 9a13031

Browse files
authored
Migrate to Dart 3.0 (#1517)
#1512 (5fb3b3b) bumped the minimum Flutter SDK to 3.10, but did not change the minimum Dart SDK. This PR changes the Dart SDK to 3.0 minimum, enabling the new features and performance benefits. In addition, this PR: * Removes the Tuple dependency in favour of Records * Uses new pattern matching switches in some locations * Seals the `TileDisplay` class to benefit from new pattern matching switches, instead of switching on `runtimeType` * Deprecates `TileUpdateTransformers.alwaysLoadAndPrune`, as it should be unnecessary compared to `ignoreTapEvents` * Improves some documentation * Includes some other more minor improvements/changes This PR also fixes the failing Android builds by upgrading Gradle.
1 parent 7538c66 commit 9a13031

21 files changed

+171
-188
lines changed

example/android/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
buildscript {
2-
ext.kotlin_version = '1.6.20'
2+
ext.kotlin_version = '1.8.21'
33
repositories {
44
google()
55
jcenter()

example/android/gradle/wrapper/gradle-wrapper.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip

example/lib/pages/marker_anchor.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class MarkerAnchorPage extends StatefulWidget {
1515
}
1616

1717
class MarkerAnchorPageState extends State<MarkerAnchorPage> {
18-
late AnchorPos<dynamic> anchorPos;
18+
late AnchorPos anchorPos;
1919

2020
@override
2121
void initState() {

example/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ publish_to: "none"
44
version: 5.0.0
55

66
environment:
7-
sdk: ">=2.18.0 <4.0.0"
7+
sdk: ">=3.0.0 <4.0.0"
88
flutter: ">=3.10.0"
99

1010
dependencies:

lib/src/core/point.dart

-5
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,4 @@ class CustomPoint<T extends num> extends math.Point<T> {
8080

8181
@override
8282
String toString() => 'CustomPoint ($x, $y)';
83-
84-
/// Create new [CustomPoint] with [x] and [y] multiplied by [n]
85-
CustomPoint<T> multiplyBy(num n) {
86-
return this * n;
87-
}
8883
}

lib/src/geo/crs/crs.dart

+9-10
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import 'package:flutter_map/src/core/point.dart';
55
import 'package:latlong2/latlong.dart';
66
import 'package:meta/meta.dart';
77
import 'package:proj4dart/proj4dart.dart' as proj4;
8-
import 'package:tuple/tuple.dart';
98

109
/// An abstract representation of a
1110
/// [Coordinate Reference System](https://bit.ly/3iVKpja).
@@ -68,9 +67,9 @@ abstract class Crs {
6867

6968
bool get infinite;
7069

71-
Tuple2<double, double>? get wrapLng;
70+
(double, double)? get wrapLng;
7271

73-
Tuple2<double, double>? get wrapLat;
72+
(double, double)? get wrapLat;
7473
}
7574

7675
// Custom CRS for non geographical maps
@@ -93,21 +92,21 @@ class CrsSimple extends Crs {
9392
bool get infinite => false;
9493

9594
@override
96-
Tuple2<double, double>? get wrapLat => null;
95+
(double, double)? get wrapLat => null;
9796

9897
@override
99-
Tuple2<double, double>? get wrapLng => null;
98+
(double, double)? get wrapLng => null;
10099
}
101100

102101
abstract class Earth extends Crs {
103102
@override
104103
bool get infinite => false;
105104

106105
@override
107-
final Tuple2<double, double> wrapLng = const Tuple2(-180, 180);
106+
final (double, double) wrapLng = const (-180, 180);
108107

109108
@override
110-
final Tuple2<double, double>? wrapLat = null;
109+
final (double, double)? wrapLat = null;
111110

112111
const Earth() : super();
113112
}
@@ -132,7 +131,7 @@ class Epsg3857 extends Earth {
132131

133132
// Epsg3857 seems to have latitude limits. https://epsg.io/3857
134133
//@override
135-
//Tuple2<double, double> get wrapLat => const Tuple2(-85.06, 85.06);
134+
//(double, double) get wrapLat => const (-85.06, 85.06);
136135
}
137136

138137
/// A common CRS among GIS enthusiasts. Uses simple Equirectangular projection.
@@ -167,10 +166,10 @@ class Proj4Crs extends Crs {
167166
final bool infinite;
168167

169168
@override
170-
final Tuple2<double, double>? wrapLat = null;
169+
final (double, double)? wrapLat = null;
171170

172171
@override
173-
final Tuple2<double, double>? wrapLng = null;
172+
final (double, double)? wrapLng = null;
174173

175174
final List<Transformation>? _transformations;
176175

lib/src/gestures/map_events.dart

+38-42
Original file line numberDiff line numberDiff line change
@@ -72,48 +72,44 @@ abstract class MapEventWithMove extends MapEvent {
7272
required bool hasGesture,
7373
required MapEventSource source,
7474
String? id,
75-
}) {
76-
switch (source) {
77-
case MapEventSource.flingAnimationController:
78-
return MapEventFlingAnimation(
79-
center: oldCenter,
80-
zoom: oldZoom,
81-
targetCenter: targetCenter,
82-
targetZoom: targetZoom,
83-
source: source,
84-
);
85-
case MapEventSource.doubleTapZoomAnimationController:
86-
return MapEventDoubleTapZoom(
87-
center: oldCenter,
88-
zoom: oldZoom,
89-
targetCenter: targetCenter,
90-
targetZoom: targetZoom,
91-
source: source,
92-
);
93-
case MapEventSource.scrollWheel:
94-
return MapEventScrollWheelZoom(
95-
center: oldCenter,
96-
zoom: oldZoom,
97-
targetCenter: targetCenter,
98-
targetZoom: targetZoom,
99-
source: source,
100-
);
101-
case MapEventSource.onDrag:
102-
case MapEventSource.onMultiFinger:
103-
case MapEventSource.mapController:
104-
case MapEventSource.custom:
105-
return MapEventMove(
106-
id: id,
107-
center: oldCenter,
108-
zoom: oldZoom,
109-
targetCenter: targetCenter,
110-
targetZoom: targetZoom,
111-
source: source,
112-
);
113-
default:
114-
return null;
115-
}
116-
}
75+
}) =>
76+
switch (source) {
77+
MapEventSource.flingAnimationController => MapEventFlingAnimation(
78+
center: oldCenter,
79+
zoom: oldZoom,
80+
targetCenter: targetCenter,
81+
targetZoom: targetZoom,
82+
source: source,
83+
),
84+
MapEventSource.doubleTapZoomAnimationController =>
85+
MapEventDoubleTapZoom(
86+
center: oldCenter,
87+
zoom: oldZoom,
88+
targetCenter: targetCenter,
89+
targetZoom: targetZoom,
90+
source: source,
91+
),
92+
MapEventSource.scrollWheel => MapEventScrollWheelZoom(
93+
center: oldCenter,
94+
zoom: oldZoom,
95+
targetCenter: targetCenter,
96+
targetZoom: targetZoom,
97+
source: source,
98+
),
99+
MapEventSource.onDrag ||
100+
MapEventSource.onMultiFinger ||
101+
MapEventSource.mapController ||
102+
MapEventSource.custom =>
103+
MapEventMove(
104+
id: id,
105+
center: oldCenter,
106+
zoom: oldZoom,
107+
targetCenter: targetCenter,
108+
targetZoom: targetZoom,
109+
source: source,
110+
),
111+
_ => null,
112+
};
117113
}
118114

119115
/// Event which is fired when map is tapped

lib/src/layer/attribution_layer/animation.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import 'package:flutter_map/src/layer/attribution_layer/rich.dart';
1111
/// [AnimatedSwitcher], but its curve and duration can still be customized
1212
/// through [buttonDuration] and [buttonCurve].
1313
///
14-
/// Can be extensivley customized by implementing a custom
14+
/// Can be extensively customized by implementing a custom
1515
/// [RichAttributionWidgetAnimation], or the prebuilt [FadeRAWA] and
1616
/// [ScaleRAWA] animations can be used with limited customization.
1717
abstract class RichAttributionWidgetAnimation {

lib/src/layer/label.dart

+4-9
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,10 @@ class Label {
1515
bool rotate = false,
1616
PolygonLabelPlacement labelPlacement = PolygonLabelPlacement.polylabel,
1717
}) {
18-
late Offset placementPoint;
19-
switch (labelPlacement) {
20-
case PolygonLabelPlacement.centroid:
21-
placementPoint = _computeCentroid(points);
22-
break;
23-
case PolygonLabelPlacement.polylabel:
24-
placementPoint = _computePolylabel(points);
25-
break;
26-
}
18+
final placementPoint = switch (labelPlacement) {
19+
PolygonLabelPlacement.centroid => _computeCentroid(points),
20+
PolygonLabelPlacement.polylabel => _computePolylabel(points),
21+
};
2722

2823
var dx = placementPoint.dx;
2924
var dy = placementPoint.dy;

lib/src/layer/marker_layer.dart

+25-42
Original file line numberDiff line numberDiff line change
@@ -14,51 +14,34 @@ class Anchor {
1414
: left = _leftOffset(width, alignOpt),
1515
top = _topOffset(height, alignOpt);
1616

17-
static double _leftOffset(double width, AnchorAlign alignOpt) {
18-
switch (alignOpt) {
19-
case AnchorAlign.left:
20-
return 0;
21-
case AnchorAlign.right:
22-
return width;
23-
case AnchorAlign.top:
24-
case AnchorAlign.bottom:
25-
case AnchorAlign.center:
26-
default:
27-
return width / 2;
28-
}
29-
}
30-
31-
static double _topOffset(double height, AnchorAlign alignOpt) {
32-
switch (alignOpt) {
33-
case AnchorAlign.top:
34-
return 0;
35-
case AnchorAlign.bottom:
36-
return height;
37-
case AnchorAlign.left:
38-
case AnchorAlign.right:
39-
case AnchorAlign.center:
40-
default:
41-
return height / 2;
42-
}
43-
}
44-
45-
factory Anchor.forPos(AnchorPos<dynamic>? pos, double width, double height) {
17+
static double _leftOffset(double width, AnchorAlign alignOpt) =>
18+
switch (alignOpt) {
19+
AnchorAlign.left => 0,
20+
AnchorAlign.right => width,
21+
_ => width / 2,
22+
};
23+
24+
static double _topOffset(double height, AnchorAlign alignOpt) =>
25+
switch (alignOpt) {
26+
AnchorAlign.top => 0,
27+
AnchorAlign.bottom => height,
28+
_ => height / 2,
29+
};
30+
31+
factory Anchor.forPos(AnchorPos? pos, double width, double height) {
4632
if (pos == null) return Anchor._(width, height, AnchorAlign.none);
47-
if (pos.value is AnchorAlign) {
48-
return Anchor._(width, height, pos.value as AnchorAlign);
49-
}
50-
if (pos.value is Anchor) return pos.value as Anchor;
51-
throw Exception('Unsupported AnchorPos value type: ${pos.runtimeType}.');
33+
if (pos.alignment case final align?) return Anchor._(width, height, align);
34+
if (pos.anchor case final anchor?) return anchor;
35+
throw Exception();
5236
}
5337
}
5438

55-
class AnchorPos<T> {
56-
AnchorPos._(this.value);
57-
T value;
58-
static AnchorPos<Anchor> exactly(Anchor anchor) =>
59-
AnchorPos<Anchor>._(anchor);
60-
static AnchorPos<AnchorAlign> align(AnchorAlign alignOpt) =>
61-
AnchorPos<AnchorAlign>._(alignOpt);
39+
class AnchorPos {
40+
final Anchor? anchor;
41+
final AnchorAlign? alignment;
42+
43+
AnchorPos.exactly(this.anchor) : alignment = null;
44+
AnchorPos.align(this.alignment) : anchor = null;
6245
}
6346

6447
enum AnchorAlign {
@@ -119,7 +102,7 @@ class Marker {
119102
this.rotate,
120103
this.rotateOrigin,
121104
this.rotateAlignment,
122-
AnchorPos<dynamic>? anchorPos,
105+
AnchorPos? anchorPos,
123106
}) : anchor = Anchor.forPos(anchorPos, width, height);
124107
}
125108

lib/src/layer/tile_layer/tile_bounds/tile_bounds.dart

+10-15
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import 'package:flutter_map/src/geo/latlng_bounds.dart';
44
import 'package:flutter_map/src/layer/tile_layer/tile_bounds/tile_bounds_at_zoom.dart';
55
import 'package:flutter_map/src/layer/tile_layer/tile_range.dart';
66
import 'package:latlong2/latlong.dart';
7-
import 'package:tuple/tuple.dart';
87

98
abstract class TileBounds {
109
final Crs crs;
@@ -124,30 +123,26 @@ class WrappedTileBounds extends TileBounds {
124123

125124
final tzDouble = zoom.toDouble();
126125

127-
Tuple2<int, int>? wrapX;
128-
if (crs.wrapLng != null) {
126+
(int, int)? wrapX;
127+
if (crs.wrapLng case final wrapLng?) {
129128
final wrapXMin =
130-
(crs.latLngToPoint(LatLng(0, crs.wrapLng!.item1), tzDouble).x /
131-
_tileSize)
129+
(crs.latLngToPoint(LatLng(0, wrapLng.$1), tzDouble).x / _tileSize)
132130
.floor();
133131
final wrapXMax =
134-
(crs.latLngToPoint(LatLng(0, crs.wrapLng!.item2), tzDouble).x /
135-
_tileSize)
132+
(crs.latLngToPoint(LatLng(0, wrapLng.$2), tzDouble).x / _tileSize)
136133
.ceil();
137-
wrapX = Tuple2(wrapXMin, wrapXMax - 1);
134+
wrapX = (wrapXMin, wrapXMax - 1);
138135
}
139136

140-
Tuple2<int, int>? wrapY;
141-
if (crs.wrapLat != null) {
137+
(int, int)? wrapY;
138+
if (crs.wrapLat case final wrapLat?) {
142139
final wrapYMin =
143-
(crs.latLngToPoint(LatLng(crs.wrapLat!.item1, 0), tzDouble).y /
144-
_tileSize)
140+
(crs.latLngToPoint(LatLng(wrapLat.$1, 0), tzDouble).y / _tileSize)
145141
.floor();
146142
final wrapYMax =
147-
(crs.latLngToPoint(LatLng(crs.wrapLat!.item2, 0), tzDouble).y /
148-
_tileSize)
143+
(crs.latLngToPoint(LatLng(wrapLat.$2, 0), tzDouble).y / _tileSize)
149144
.ceil();
150-
wrapY = Tuple2(wrapYMin, wrapYMax - 1);
145+
wrapY = (wrapYMin, wrapYMax - 1);
151146
}
152147

153148
return WrappedTileBoundsAtZoom(

lib/src/layer/tile_layer/tile_bounds/tile_bounds_at_zoom.dart

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'package:flutter_map/src/core/point.dart';
22
import 'package:flutter_map/src/layer/tile_layer/tile_coordinates.dart';
33
import 'package:flutter_map/src/layer/tile_layer/tile_range.dart';
4-
import 'package:tuple/tuple.dart';
54

65
abstract class TileBoundsAtZoom {
76
const TileBoundsAtZoom();
@@ -46,8 +45,8 @@ class DiscreteTileBoundsAtZoom extends TileBoundsAtZoom {
4645
class WrappedTileBoundsAtZoom extends TileBoundsAtZoom {
4746
final DiscreteTileRange tileRange;
4847
final bool wrappedAxisIsAlwaysInBounds;
49-
final Tuple2<int, int>? wrapX;
50-
final Tuple2<int, int>? wrapY;
48+
final (int, int)? wrapX;
49+
final (int, int)? wrapY;
5150

5251
const WrappedTileBoundsAtZoom({
5352
required this.tileRange,
@@ -120,9 +119,9 @@ class WrappedTileBoundsAtZoom extends TileBoundsAtZoom {
120119
}
121120

122121
/// Wrap [x] to be within [range] inclusive.
123-
int _wrapInt(int x, Tuple2<int, int> range) {
124-
final d = range.item2 + 1 - range.item1;
125-
return ((x - range.item1) % d + d) % d + range.item1;
122+
int _wrapInt(int x, (int, int) range) {
123+
final d = range.$2 + 1 - range.$1;
124+
return ((x - range.$1) % d + d) % d + range.$1;
126125
}
127126

128127
@override

lib/src/layer/tile_layer/tile_coordinates.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'package:flutter_map/flutter_map.dart';
55
class TileCoordinates extends CustomPoint<int> {
66
final int z;
77

8-
const TileCoordinates(int x, int y, this.z) : super(x, y);
8+
const TileCoordinates(super.x, super.y, this.z);
99

1010
String get key => '$x:$y:$z';
1111

0 commit comments

Comments
 (0)