feat(map): migrate to flutter_map 8.2 with OSM-compliant tiles
This commit is contained in:
@ -1,14 +1,7 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:dio_cache_interceptor_hive_store/dio_cache_interceptor_hive_store.dart';
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:flutter_map_cache/flutter_map_cache.dart';
|
||||
import 'package:flutter_map_compass/flutter_map_compass.dart';
|
||||
import 'package:flutter_map_math/flutter_geo_math.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
@ -18,15 +11,9 @@ import 'package:ot_viewer_app/settings_page.dart';
|
||||
import 'package:ot_viewer_app/user_path_bloc.dart';
|
||||
import 'package:ot_viewer_app/util.dart';
|
||||
import 'package:ot_viewer_app/web_socket_cubit.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'owntracks_api.dart';
|
||||
import 'dart:math' as math;
|
||||
|
||||
Future<String> getPath() async {
|
||||
final cacheDirectory = await getTemporaryDirectory();
|
||||
return cacheDirectory.path;
|
||||
}
|
||||
|
||||
class MapPage extends StatefulWidget {
|
||||
const MapPage({super.key});
|
||||
|
||||
@ -55,56 +42,50 @@ class _MapPageState extends State<MapPage> {
|
||||
refreshCubit.stream.listen((_) => cubit.reconnect());
|
||||
return cubit;
|
||||
},
|
||||
child: FutureBuilder<String>(
|
||||
future: getPath(),
|
||||
builder: (something, tempPath) =>
|
||||
BlocBuilder<SettingsCubit, SettingsState>(
|
||||
builder: (context, state) {
|
||||
if (tempPath.data == null) {
|
||||
return const Center(child: Text('Loading Map...'));
|
||||
}
|
||||
return Stack(children: [
|
||||
FlutterMap(
|
||||
child: BlocBuilder<SettingsCubit, SettingsState>(
|
||||
builder: (context, state) {
|
||||
return Stack(children: [
|
||||
FlutterMap(
|
||||
mapController: _mapController,
|
||||
options: const MapOptions(
|
||||
initialCenter: LatLng(48.3285, 9.8942),
|
||||
initialZoom: 13.0,
|
||||
),
|
||||
children: [
|
||||
TileLayer(
|
||||
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
userAgentPackageName: 'ot_viewer_app',
|
||||
tileProvider: NetworkTileProvider(
|
||||
headers: {
|
||||
'User-Agent': 'ot_viewer_app/1.0',
|
||||
},
|
||||
),
|
||||
),
|
||||
...state.activeDevices.map((id) =>
|
||||
UserPath(key: ValueKey(id), device: id, settings: state)),
|
||||
const MapCompass.cupertino(
|
||||
rotationDuration: Duration(milliseconds: 600)),
|
||||
// CurrentLocationLayer(), TODO: add permission
|
||||
RichAttributionWidget(
|
||||
attributions: [
|
||||
TextSourceAttribution(
|
||||
'OpenStreetMap contributors',
|
||||
onTap: () =>
|
||||
(Uri.parse('https://openstreetmap.org/copyright')),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
left: 16,
|
||||
child: TrackerSelector(
|
||||
mapController: _mapController,
|
||||
options: const MapOptions(
|
||||
initialCenter: LatLng(48.3285, 9.8942),
|
||||
initialZoom: 13.0,
|
||||
),
|
||||
children: [
|
||||
TileLayer(
|
||||
urlTemplate:
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
tileProvider: CachedTileProvider(
|
||||
maxStale: const Duration(days: 30),
|
||||
store: HiveCacheStore(tempPath.data!,
|
||||
hiveBoxName: 'HiveCacheStore')),
|
||||
),
|
||||
...state.activeDevices.map((id) =>
|
||||
UserPath(key: ValueKey(id), device: id, settings: state)),
|
||||
const MapCompass.cupertino(
|
||||
rotationDuration: Duration(milliseconds: 600)),
|
||||
// CurrentLocationLayer(), TODO: add permission
|
||||
RichAttributionWidget(
|
||||
attributions: [
|
||||
TextSourceAttribution(
|
||||
'OpenStreetMap contributors',
|
||||
onTap: () =>
|
||||
(Uri.parse('https://openstreetmap.org/copyright')),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
left: 16,
|
||||
child: TrackerSelector(
|
||||
mapController: _mapController,
|
||||
),
|
||||
),
|
||||
]);
|
||||
},
|
||||
),
|
||||
),
|
||||
]);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -140,7 +121,6 @@ class _UserPathState extends State<UserPath> {
|
||||
if (state
|
||||
case LocationUpdateReceived(
|
||||
:final position,
|
||||
:final deviceId
|
||||
)) {
|
||||
if (userPathBloc.deviceId == state.deviceId) {
|
||||
userPathBloc.add(UserPathLiveSubscriptionUpdate(position));
|
||||
@ -161,15 +141,15 @@ class _UserPathState extends State<UserPath> {
|
||||
.add(UserPathLoginDataChanged(widget.settings));
|
||||
|
||||
print("rebuild");
|
||||
final _istate = state as MainUserPathState;
|
||||
final mainState = state as MainUserPathState;
|
||||
// make markers
|
||||
final List<Marker> markers = [];
|
||||
|
||||
if (state.livePoints.isNotEmpty) {
|
||||
if (mainState.livePoints.isNotEmpty) {
|
||||
markers.add(Marker(
|
||||
width: 500,
|
||||
height: 100,
|
||||
point: state.livePoints.last.asLatLng,
|
||||
point: mainState.livePoints.last.asLatLng,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
@ -205,10 +185,11 @@ class _UserPathState extends State<UserPath> {
|
||||
// Create fancy fade-out and blended line (TODO: make distance based. use flutter_map_math)
|
||||
List<List<LatLng>> segments = [];
|
||||
List<Color> colors = [];
|
||||
if (state.initialPoints.isNotEmpty) {
|
||||
final allPoints =
|
||||
state.initialPoints.map((e) => LatLng(e.lat, e.lon)).toList();
|
||||
final segmentCount = math.min(100, allPoints.length);
|
||||
if (mainState.initialPoints.isNotEmpty) {
|
||||
final allPoints = mainState.initialPoints
|
||||
.map((e) => LatLng(e.lat, e.lon))
|
||||
.toList();
|
||||
final int segmentCount = math.min(100, allPoints.length);
|
||||
final pointsPerSegment = (allPoints.length / segmentCount).ceil();
|
||||
|
||||
// Split the points into segments and generate colors
|
||||
@ -259,7 +240,7 @@ class _UserPathState extends State<UserPath> {
|
||||
key: ValueKey('${widget.device}_liveLines'),
|
||||
polylines: [
|
||||
Polyline(
|
||||
points: state.livePoints
|
||||
points: mainState.livePoints
|
||||
.map((e) => LatLng(e.lat, e.lon))
|
||||
.toList(),
|
||||
strokeWidth: 4.0,
|
||||
|
||||
Reference in New Issue
Block a user