info: use overlay buttons and added map style button
This commit is contained in:
parent
2528370f73
commit
5bca875f83
8 changed files with 312 additions and 215 deletions
51
lib/widgets/common/action_delegates/map_style_dialog.dart
Normal file
51
lib/widgets/common/action_delegates/map_style_dialog.dart
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import 'package:aves/model/settings.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
import '../dialog.dart';
|
||||||
|
|
||||||
|
class MapStyleDialog extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_MapStyleDialogState createState() => _MapStyleDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MapStyleDialogState extends State<MapStyleDialog> {
|
||||||
|
EntryMapStyle _selectedStyle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selectedStyle = settings.infoMapStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AvesDialog(
|
||||||
|
title: 'Map Style',
|
||||||
|
scrollableContent: EntryMapStyle.values.map((style) => _buildRadioListTile(style, style.name)).toList(),
|
||||||
|
actions: [
|
||||||
|
FlatButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: Text('Cancel'.toUpperCase()),
|
||||||
|
),
|
||||||
|
FlatButton(
|
||||||
|
onPressed: () => Navigator.pop(context, _selectedStyle),
|
||||||
|
child: Text('Apply'.toUpperCase()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildRadioListTile(EntryMapStyle style, String title) => RadioListTile<EntryMapStyle>(
|
||||||
|
value: style,
|
||||||
|
groupValue: _selectedStyle,
|
||||||
|
onChanged: (style) => setState(() => _selectedStyle = style),
|
||||||
|
title: Text(
|
||||||
|
title,
|
||||||
|
softWrap: false,
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -46,6 +46,7 @@ class AIcons {
|
||||||
static const IconData share = OMIcons.share;
|
static const IconData share = OMIcons.share;
|
||||||
static const IconData sort = OMIcons.sort;
|
static const IconData sort = OMIcons.sort;
|
||||||
static const IconData stats = OMIcons.pieChart;
|
static const IconData stats = OMIcons.pieChart;
|
||||||
|
static const IconData style = OMIcons.palette;
|
||||||
static const IconData zoomIn = OMIcons.add;
|
static const IconData zoomIn = OMIcons.add;
|
||||||
static const IconData zoomOut = OMIcons.remove;
|
static const IconData zoomOut = OMIcons.remove;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:aves/utils/geo_utils.dart';
|
||||||
import 'package:aves/widgets/common/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/info/maps/buttons.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/maps/google_map.dart';
|
import 'package:aves/widgets/fullscreen/info/maps/google_map.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/maps/leaflet_map.dart';
|
import 'package:aves/widgets/fullscreen/info/maps/leaflet_map.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -94,20 +95,25 @@ class _LocationSectionState extends State<LocationSection> {
|
||||||
padding: EdgeInsets.only(bottom: 8),
|
padding: EdgeInsets.only(bottom: 8),
|
||||||
child: SectionRow(AIcons.location),
|
child: SectionRow(AIcons.location),
|
||||||
),
|
),
|
||||||
if (settings.infoMapStyle == EntryMapStyle.google)
|
NotificationListener(
|
||||||
EntryGoogleMap(
|
onNotification: (notification) {
|
||||||
markerId: entry.uri ?? entry.path,
|
if (notification is MapStyleChangedNotification) setState(() {});
|
||||||
latLng: entry.latLng,
|
return false;
|
||||||
geoUri: entry.geoUri,
|
},
|
||||||
initialZoom: settings.infoMapZoom,
|
child: settings.infoMapStyle == EntryMapStyle.google
|
||||||
)
|
? EntryGoogleMap(
|
||||||
else
|
markerId: entry.uri ?? entry.path,
|
||||||
EntryLeafletMap(
|
latLng: entry.latLng,
|
||||||
latLng: entry.latLng,
|
geoUri: entry.geoUri,
|
||||||
geoUri: entry.geoUri,
|
initialZoom: settings.infoMapZoom,
|
||||||
initialZoom: settings.infoMapZoom,
|
)
|
||||||
style: settings.infoMapStyle,
|
: EntryLeafletMap(
|
||||||
),
|
latLng: entry.latLng,
|
||||||
|
geoUri: entry.geoUri,
|
||||||
|
initialZoom: settings.infoMapZoom,
|
||||||
|
style: settings.infoMapStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
if (location.isNotEmpty)
|
if (location.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 8),
|
padding: EdgeInsets.only(top: 8),
|
||||||
|
|
112
lib/widgets/fullscreen/info/maps/buttons.dart
Normal file
112
lib/widgets/fullscreen/info/maps/buttons.dart
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import 'package:aves/model/settings.dart';
|
||||||
|
import 'package:aves/services/android_app_service.dart';
|
||||||
|
import 'package:aves/widgets/common/action_delegates/map_style_dialog.dart';
|
||||||
|
import 'package:aves/widgets/common/fx/blurred.dart';
|
||||||
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class MapButtonPanel extends StatelessWidget {
|
||||||
|
final String geoUri;
|
||||||
|
final void Function(double amount) zoomBy;
|
||||||
|
|
||||||
|
static const BorderRadius mapBorderRadius = BorderRadius.all(Radius.circular(24)); // to match button circles
|
||||||
|
static const double padding = 4;
|
||||||
|
|
||||||
|
const MapButtonPanel({
|
||||||
|
@required this.geoUri,
|
||||||
|
@required this.zoomBy,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Positioned.fill(
|
||||||
|
child: Align(
|
||||||
|
alignment: AlignmentDirectional.centerEnd,
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(padding),
|
||||||
|
child: TooltipTheme(
|
||||||
|
data: TooltipTheme.of(context).copyWith(
|
||||||
|
preferBelow: false,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
MapOverlayButton(
|
||||||
|
icon: AIcons.style,
|
||||||
|
onPressed: () async {
|
||||||
|
final style = await showDialog<EntryMapStyle>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => MapStyleDialog(),
|
||||||
|
);
|
||||||
|
if (style != null) {
|
||||||
|
settings.infoMapStyle = style;
|
||||||
|
MapStyleChangedNotification().dispatch(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: 'Style map...',
|
||||||
|
),
|
||||||
|
SizedBox(height: padding),
|
||||||
|
MapOverlayButton(
|
||||||
|
icon: AIcons.openInNew,
|
||||||
|
onPressed: () => AndroidAppService.openMap(geoUri),
|
||||||
|
tooltip: 'Show on map...',
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
MapOverlayButton(
|
||||||
|
icon: AIcons.zoomIn,
|
||||||
|
onPressed: () => zoomBy(1),
|
||||||
|
tooltip: 'Zoom in',
|
||||||
|
),
|
||||||
|
SizedBox(height: padding),
|
||||||
|
MapOverlayButton(
|
||||||
|
icon: AIcons.zoomOut,
|
||||||
|
onPressed: () => zoomBy(-1),
|
||||||
|
tooltip: 'Zoom out',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapOverlayButton extends StatelessWidget {
|
||||||
|
final IconData icon;
|
||||||
|
final String tooltip;
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
|
||||||
|
const MapOverlayButton({
|
||||||
|
@required this.icon,
|
||||||
|
@required this.tooltip,
|
||||||
|
@required this.onPressed,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlurredOval(
|
||||||
|
child: Material(
|
||||||
|
type: MaterialType.circle,
|
||||||
|
color: FullscreenOverlay.backgroundColor,
|
||||||
|
child: Ink(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: FullscreenOverlay.buildBorder(context),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
iconSize: 20,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
icon: Icon(icon),
|
||||||
|
onPressed: onPressed,
|
||||||
|
tooltip: tooltip,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapStyleChangedNotification extends Notification {}
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:aves/model/settings.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
import 'package:aves/services/android_app_service.dart';
|
import 'package:aves/widgets/fullscreen/info/maps/buttons.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
@ -38,74 +37,62 @@ class EntryGoogleMapState extends State<EntryGoogleMap> with AutomaticKeepAliveC
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
final accentHue = HSVColor.fromColor(Theme.of(context).accentColor).hue;
|
return Stack(
|
||||||
return Row(
|
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
_buildMap(),
|
||||||
child: GestureDetector(
|
Positioned.fill(
|
||||||
onScaleStart: (details) {
|
child: Align(
|
||||||
// absorb scale gesture here to prevent scrolling
|
alignment: AlignmentDirectional.centerEnd,
|
||||||
// and triggering by mistake a move to the image page above
|
child: MapButtonPanel(
|
||||||
},
|
geoUri: widget.geoUri,
|
||||||
child: ClipRRect(
|
zoomBy: _zoomBy,
|
||||||
borderRadius: BorderRadius.circular(16),
|
|
||||||
child: Container(
|
|
||||||
color: Colors.white70,
|
|
||||||
height: 200,
|
|
||||||
child: GoogleMap(
|
|
||||||
// GoogleMap init perf issue: https://github.com/flutter/flutter/issues/28493
|
|
||||||
initialCameraPosition: CameraPosition(
|
|
||||||
target: widget.latLng,
|
|
||||||
zoom: widget.initialZoom,
|
|
||||||
),
|
|
||||||
onMapCreated: (controller) => setState(() => _controller = controller),
|
|
||||||
rotateGesturesEnabled: false,
|
|
||||||
scrollGesturesEnabled: false,
|
|
||||||
zoomControlsEnabled: false,
|
|
||||||
zoomGesturesEnabled: false,
|
|
||||||
liteModeEnabled: false,
|
|
||||||
tiltGesturesEnabled: false,
|
|
||||||
myLocationEnabled: false,
|
|
||||||
myLocationButtonEnabled: false,
|
|
||||||
markers: {
|
|
||||||
Marker(
|
|
||||||
markerId: MarkerId(widget.markerId),
|
|
||||||
icon: BitmapDescriptor.defaultMarkerWithHue(accentHue),
|
|
||||||
position: widget.latLng,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
TooltipTheme(
|
|
||||||
data: TooltipTheme.of(context).copyWith(
|
|
||||||
preferBelow: false,
|
|
||||||
),
|
|
||||||
child: Column(children: [
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(AIcons.zoomIn),
|
|
||||||
onPressed: _controller == null ? null : () => _zoomBy(1),
|
|
||||||
tooltip: 'Zoom in',
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(AIcons.zoomOut),
|
|
||||||
onPressed: _controller == null ? null : () => _zoomBy(-1),
|
|
||||||
tooltip: 'Zoom out',
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(AIcons.openInNew),
|
|
||||||
onPressed: () => AndroidAppService.openMap(widget.geoUri),
|
|
||||||
tooltip: 'Show on map...',
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildMap() {
|
||||||
|
final accentHue = HSVColor.fromColor(Theme.of(context).accentColor).hue;
|
||||||
|
return GestureDetector(
|
||||||
|
onScaleStart: (details) {
|
||||||
|
// absorb scale gesture here to prevent scrolling
|
||||||
|
// and triggering by mistake a move to the image page above
|
||||||
|
},
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: MapButtonPanel.mapBorderRadius,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white70,
|
||||||
|
height: 200,
|
||||||
|
child: GoogleMap(
|
||||||
|
// GoogleMap init perf issue: https://github.com/flutter/flutter/issues/28493
|
||||||
|
initialCameraPosition: CameraPosition(
|
||||||
|
target: widget.latLng,
|
||||||
|
zoom: widget.initialZoom,
|
||||||
|
),
|
||||||
|
onMapCreated: (controller) => setState(() => _controller = controller),
|
||||||
|
rotateGesturesEnabled: false,
|
||||||
|
scrollGesturesEnabled: false,
|
||||||
|
zoomControlsEnabled: false,
|
||||||
|
zoomGesturesEnabled: false,
|
||||||
|
liteModeEnabled: false,
|
||||||
|
tiltGesturesEnabled: false,
|
||||||
|
myLocationEnabled: false,
|
||||||
|
myLocationButtonEnabled: false,
|
||||||
|
markers: {
|
||||||
|
Marker(
|
||||||
|
markerId: MarkerId(widget.markerId),
|
||||||
|
icon: BitmapDescriptor.defaultMarkerWithHue(accentHue),
|
||||||
|
position: widget.latLng,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _zoomBy(double amount) {
|
void _zoomBy(double amount) {
|
||||||
settings.infoMapZoom += amount;
|
settings.infoMapZoom += amount;
|
||||||
_controller.animateCamera(CameraUpdate.zoomBy(amount));
|
_controller.animateCamera(CameraUpdate.zoomBy(amount));
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:aves/model/settings.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
import 'package:aves/services/android_app_service.dart';
|
import 'package:aves/widgets/fullscreen/info/maps/buttons.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
|
||||||
import 'package:aves/widgets/fullscreen/info/maps/scale_layer.dart';
|
import 'package:aves/widgets/fullscreen/info/maps/scale_layer.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_map/flutter_map.dart';
|
import 'package:flutter_map/flutter_map.dart';
|
||||||
|
@ -46,83 +45,16 @@ class EntryLeafletMapState extends State<EntryLeafletMap> with AutomaticKeepAliv
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
final accentColor = Theme.of(context).accentColor;
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Stack(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
_buildMap(),
|
||||||
child: GestureDetector(
|
MapButtonPanel(
|
||||||
onScaleStart: (details) {
|
geoUri: widget.geoUri,
|
||||||
// absorb scale gesture here to prevent scrolling
|
zoomBy: _zoomBy,
|
||||||
// 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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
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(),
|
_buildAttribution(),
|
||||||
|
@ -130,6 +62,55 @@ class EntryLeafletMapState extends State<EntryLeafletMap> with AutomaticKeepAliv
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildMap() {
|
||||||
|
return GestureDetector(
|
||||||
|
onScaleStart: (details) {
|
||||||
|
// absorb scale gesture here to prevent scrolling
|
||||||
|
// and triggering by mistake a move to the image page above
|
||||||
|
},
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: MapButtonPanel.mapBorderRadius,
|
||||||
|
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: Theme.of(context).accentColor,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
anchorPos: AnchorPos.align(AnchorAlign.top),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
mapController: _mapController,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildMapLayer() {
|
Widget _buildMapLayer() {
|
||||||
switch (widget.style) {
|
switch (widget.style) {
|
||||||
case EntryMapStyle.osmHot:
|
case EntryMapStyle.osmHot:
|
||||||
|
@ -144,39 +125,38 @@ class EntryLeafletMapState extends State<EntryLeafletMap> with AutomaticKeepAliv
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAttribution() {
|
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) {
|
switch (widget.style) {
|
||||||
case EntryMapStyle.osmHot:
|
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/)';
|
return _buildAttributionMarkdown('© [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.stamenToner:
|
||||||
case EntryMapStyle.stamenWatercolor:
|
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';
|
return _buildAttributionMarkdown('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:
|
default:
|
||||||
return null;
|
return SizedBox.shrink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildAttributionMarkdown(String data) {
|
||||||
|
return Markdown(
|
||||||
|
data: data,
|
||||||
|
selectable: true,
|
||||||
|
styleSheet: MarkdownStyleSheet(
|
||||||
|
a: TextStyle(color: Theme.of(context).accentColor),
|
||||||
|
p: TextStyle(color: Colors.white70, fontSize: 13, fontFamily: 'Concourse'),
|
||||||
|
),
|
||||||
|
onTapLink: (url) async {
|
||||||
|
if (await canLaunch(url)) {
|
||||||
|
await launch(url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 0),
|
||||||
|
shrinkWrap: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _zoomBy(double amount) {
|
void _zoomBy(double amount) {
|
||||||
|
if (_mapController == null) return;
|
||||||
|
|
||||||
final endZoom = (settings.infoMapZoom + amount).clamp(1.0, 16.0);
|
final endZoom = (settings.infoMapZoom + amount).clamp(1.0, 16.0);
|
||||||
settings.infoMapZoom = endZoom;
|
settings.infoMapZoom = endZoom;
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ class _HomePageState extends State<HomePage> {
|
||||||
return SingleFullscreenPage(entry: _viewerEntry);
|
return SingleFullscreenPage(entry: _viewerEntry);
|
||||||
}
|
}
|
||||||
if (_mediaStore != null) {
|
if (_mediaStore != null) {
|
||||||
switch(settings.launchPage) {
|
switch (settings.launchPage) {
|
||||||
case LaunchPage.albums:
|
case LaunchPage.albums:
|
||||||
return AlbumListPage(source: _mediaStore);
|
return AlbumListPage(source: _mediaStore);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:aves/model/settings.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/location_section.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class SettingsPage extends StatelessWidget {
|
class SettingsPage extends StatelessWidget {
|
||||||
|
@ -27,16 +26,6 @@ class SettingsPage extends StatelessWidget {
|
||||||
Flexible(child: LaunchPageSelector()),
|
Flexible(child: LaunchPageSelector()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
|
||||||
Text('Maps', style: Constants.titleTextStyle),
|
|
||||||
Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text('Storage:'),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Flexible(child: InfoMapStyleSelector()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -46,35 +35,6 @@ class SettingsPage extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InfoMapStyleSelector extends StatefulWidget {
|
|
||||||
@override
|
|
||||||
_InfoMapStyleSelectorState createState() => _InfoMapStyleSelectorState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _InfoMapStyleSelectorState extends State<InfoMapStyleSelector> {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return DropdownButton<EntryMapStyle>(
|
|
||||||
items: EntryMapStyle.values
|
|
||||||
.map((selected) => DropdownMenuItem(
|
|
||||||
value: selected,
|
|
||||||
child: Text(
|
|
||||||
selected.name,
|
|
||||||
softWrap: false,
|
|
||||||
overflow: TextOverflow.fade,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
value: settings.infoMapStyle,
|
|
||||||
onChanged: (selected) {
|
|
||||||
settings.infoMapStyle = selected;
|
|
||||||
setState(() {});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LaunchPageSelector extends StatefulWidget {
|
class LaunchPageSelector extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_LaunchPageSelectorState createState() => _LaunchPageSelectorState();
|
_LaunchPageSelectorState createState() => _LaunchPageSelectorState();
|
||||||
|
|
Loading…
Reference in a new issue