From f98400179bb8f8ad451858ba45415e5f148caa5f Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Mon, 17 Aug 2020 10:40:53 +0900 Subject: [PATCH] info: added map credits --- .../fullscreen/info/maps/leaflet_map.dart | 176 +++++++++++------- 1 file changed, 107 insertions(+), 69 deletions(-) diff --git a/lib/widgets/fullscreen/info/maps/leaflet_map.dart b/lib/widgets/fullscreen/info/maps/leaflet_map.dart index 8c356cf90..464a46607 100644 --- a/lib/widgets/fullscreen/info/maps/leaflet_map.dart +++ b/lib/widgets/fullscreen/info/maps/leaflet_map.dart @@ -4,8 +4,10 @@ import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/fullscreen/info/maps/scale_layer.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:latlong/latlong.dart'; import 'package:tuple/tuple.dart'; +import 'package:url_launcher/url_launcher.dart'; import '../location_section.dart'; @@ -45,79 +47,85 @@ class EntryLeafletMapState extends State with AutomaticKeepAliv Widget build(BuildContext context) { super.build(context); final accentColor = Theme.of(context).accentColor; - return Row( + return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: GestureDetector( - onScaleStart: (details) { - // absorb scale gesture here to prevent scrolling - // and triggering by mistake a move to the image page above - }, - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: Container( - color: Colors.white70, - height: 200, - child: FlutterMap( - options: MapOptions( - center: widget.latLng, - zoom: widget.initialZoom, - interactive: false, - ), - children: [ - _buildMapLayer(), - ScaleLayerWidget( - options: ScaleLayerOptions(), - ), - MarkerLayerWidget( - options: MarkerLayerOptions( - markers: [ - Marker( - width: markerSize, - height: markerSize, - point: widget.latLng, - builder: (ctx) { - return Icon( - Icons.place, - size: markerSize, - color: accentColor, - ); - }, - anchorPos: AnchorPos.align(AnchorAlign.top), - ), - ], + Row( + children: [ + Expanded( + child: GestureDetector( + onScaleStart: (details) { + // absorb scale gesture here to prevent scrolling + // and triggering by mistake a move to the image page above + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: Container( + color: Colors.white70, + height: 200, + child: FlutterMap( + options: MapOptions( + center: widget.latLng, + zoom: widget.initialZoom, + interactive: false, ), + children: [ + _buildMapLayer(), + ScaleLayerWidget( + options: ScaleLayerOptions(), + ), + MarkerLayerWidget( + options: MarkerLayerOptions( + markers: [ + Marker( + width: markerSize, + height: markerSize, + point: widget.latLng, + builder: (ctx) { + return Icon( + Icons.place, + size: markerSize, + color: accentColor, + ); + }, + anchorPos: AnchorPos.align(AnchorAlign.top), + ), + ], + ), + ), + ], + mapController: _mapController, ), - ], - mapController: _mapController, + ), ), ), ), - ), + SizedBox(width: 8), + TooltipTheme( + data: TooltipTheme.of(context).copyWith( + preferBelow: false, + ), + child: Column(children: [ + IconButton( + icon: Icon(AIcons.zoomIn), + onPressed: _mapController == null ? null : () => _zoomBy(1), + tooltip: 'Zoom in', + ), + IconButton( + icon: Icon(AIcons.zoomOut), + onPressed: _mapController == null ? null : () => _zoomBy(-1), + tooltip: 'Zoom out', + ), + IconButton( + icon: Icon(AIcons.openInNew), + onPressed: () => AndroidAppService.openMap(widget.geoUri), + tooltip: 'Show on map...', + ), + ]), + ) + ], ), - SizedBox(width: 8), - TooltipTheme( - data: TooltipTheme.of(context).copyWith( - preferBelow: false, - ), - child: Column(children: [ - IconButton( - icon: Icon(AIcons.zoomIn), - onPressed: _mapController == null ? null : () => _zoomBy(1), - tooltip: 'Zoom in', - ), - IconButton( - icon: Icon(AIcons.zoomOut), - onPressed: _mapController == null ? null : () => _zoomBy(-1), - tooltip: 'Zoom out', - ), - IconButton( - icon: Icon(AIcons.openInNew), - onPressed: () => AndroidAppService.openMap(widget.geoUri), - tooltip: 'Show on map...', - ), - ]), - ) + _buildAttribution(), ], ); } @@ -135,6 +143,39 @@ class EntryLeafletMapState extends State with AutomaticKeepAliv } } + Widget _buildAttribution() { + final attribution = _getAttributionMarkdown(); + return attribution != null + ? Markdown( + data: attribution, + selectable: true, + styleSheet: MarkdownStyleSheet( + a: TextStyle(color: Theme.of(context).accentColor), + p: TextStyle(fontSize: 13, fontFamily: 'Concourse'), + ), + onTapLink: (url) async { + if (await canLaunch(url)) { + await launch(url); + } + }, + padding: EdgeInsets.symmetric(vertical: 4, horizontal: 8), + shrinkWrap: true, + ) + : SizedBox.shrink(); + } + + String _getAttributionMarkdown() { + switch (widget.style) { + case EntryMapStyle.osmHot: + return '© [OpenStreetMap](https://www.openstreetmap.org/copyright) contributors, Tiles style by [Humanitarian OpenStreetMap Team](https://www.hotosm.org/) hosted by [OpenStreetMap France](https://openstreetmap.fr/)'; + case EntryMapStyle.stamenToner: + case EntryMapStyle.stamenWatercolor: + return 'Map tiles by [Stamen Design](http://stamen.com), [CC BY 3.0](http://creativecommons.org/licenses/by/3.0) — Map data © [OpenStreetMap](https://www.openstreetmap.org/copyright) contributors'; + default: + return null; + } + } + void _zoomBy(double amount) { final endZoom = (settings.infoMapZoom + amount).clamp(1.0, 16.0); settings.infoMapZoom = endZoom; @@ -162,7 +203,6 @@ class OSMHotLayer extends StatelessWidget { Widget build(BuildContext context) { return TileLayerWidget( options: TileLayerOptions( - // attribution: '© OpenStreetMap contributors, Tiles style by Humanitarian OpenStreetMap Team hosted by OpenStreetMap France' urlTemplate: 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', subdomains: ['a', 'b', 'c'], retinaMode: MediaQuery.of(context).devicePixelRatio > 1, @@ -176,7 +216,6 @@ class StamenTonerLayer extends StatelessWidget { Widget build(BuildContext context) { return TileLayerWidget( options: TileLayerOptions( - // attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors', urlTemplate: 'https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}{r}.png', subdomains: ['a', 'b', 'c', 'd'], retinaMode: MediaQuery.of(context).devicePixelRatio > 1, @@ -190,7 +229,6 @@ class StamenWatercolorLayer extends StatelessWidget { Widget build(BuildContext context) { return TileLayerWidget( options: TileLayerOptions( - // attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors', urlTemplate: 'https://stamen-tiles-{s}.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg', subdomains: ['a', 'b', 'c', 'd'], retinaMode: MediaQuery.of(context).devicePixelRatio > 1,