Locations persist. Leaflet and Rest queries

This commit is contained in:
vjrj 2018-06-10 16:20:18 +02:00
parent 7fbe5b971d
commit b5b8b3da51
13 changed files with 196 additions and 192 deletions

View file

@ -6,7 +6,6 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.2-4'
}
}

BIN
images/fire-marker-l.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

BIN
images/fire-marker-m.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

BIN
images/fire-marker-s.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

BIN
images/fire-marker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

View file

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'mainDrawer.dart';
import 'genericMap.dart';
import 'leafletMap.dart';
import 'dart:async';
import 'package:comunes_flutter/comunes_flutter.dart';
import 'colors.dart';
@ -10,6 +10,7 @@ import 'package:collection/collection.dart' show lowerBound;
import 'locationUtils.dart';
import 'globals.dart' as globals;
import 'basicLocationPersist.dart';
import 'package:http/http.dart' as http;
class ActiveFiresPage extends StatefulWidget {
static const String routeName = '/fires';
@ -36,16 +37,25 @@ class _ActiveFiresPageState extends State<ActiveFiresPage> {
title: new Text(desc),
onLongPress: () {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(
'Slide horizontally to delete this location'),
content: new Text('Slide horizontally to delete this location'),
));
},
onTap: () {
const String km = '100';
var url = 'https://fires.comunes.org/api/v1/fires-in/${globals.firesApiKey}/${loc.lat}/${loc
.lon}/$km';
/* http.post(url, body: {"name": "doodle", "color": "blue"})
.then((response) {
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
}); */
// print(url);
http.read(url).then(print);
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new GenericMap(
title: desc, latitude: loc.lat, longitude: loc.lon)));
builder: (context) =>
new LeafletMap(title: desc, location: loc)));
});
}

View file

@ -5,6 +5,10 @@ final String locationKey = 'yourlocations';
void loadYourLocations(prefs) {
List<String> yourLocations = prefs.getStringList(locationKey);
if (yourLocations == null) {
yourLocations = [];
persistYourLocations(prefs);
}
yourLocations.forEach((locationString) {
Map locationMap = json.decode(locationString);
globals.yourLocations.add(BasicLocation.fromJson(locationMap));

View file

@ -1,173 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:map_view/map_view.dart';
import 'globals.dart' as globals;
class GenericMap extends StatefulWidget {
final String title;
final double latitude;
final double longitude;
GenericMap(
{@required this.title,
@required this.latitude,
@required this.longitude});
@override
_GenericMapState createState() => new _GenericMapState(
title: this.title, latitude: this.latitude, longitude: this.longitude);
}
class _GenericMapState extends State<GenericMap> {
MapView mapView = new MapView();
CameraPosition cameraPosition;
var compositeSubscription = new CompositeSubscription();
var staticMapProvider;
Uri staticMapUri;
final String title;
Location location;
_GenericMapState(
{@required this.title, @required latitude, @required longitude}) {
MapView.setApiKey(globals.gmapKey);
this.staticMapProvider = new StaticMapProvider(globals.gmapKey);
this.location = new Location(latitude, longitude);
}
List<Marker> _markers = <Marker>[
new Marker("1", "Work", 45.523970, -122.663081, color: Colors.blue),
new Marker("2", "Nossa Familia Coffee", 45.528788, -122.684633),
];
@override
initState() {
super.initState();
cameraPosition = new CameraPosition(location, 2.0);
staticMapUri = staticMapProvider.getStaticUri(location, 12,
width: 900, height: 400, mapType: StaticMapViewType.roadmap);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Container(
height: 250.0,
child: new Stack(
children: <Widget>[
new InkWell(
child: new Center(
child: new Image.network(staticMapUri.toString()),
),
onTap: showMap,
)
],
),
),
new Container(
padding: new EdgeInsets.only(top: 10.0),
child: new Text(
"Tap the map to interact",
style: new TextStyle(fontWeight: FontWeight.bold),
),
),
]));
}
showMap() {
mapView.show(
new MapOptions(
mapViewType: MapViewType.normal,
showUserLocation: true,
initialCameraPosition: new CameraPosition(new Location(45.5235258, -122.6732493), 14.0),
title: this.title),
toolbarActions: [new ToolbarAction("Close", 1)]);
var sub = mapView.onMapReady.listen((_) {
mapView.setMarkers(_markers);
mapView.addMarker(new Marker("3", "10 Barrel", 45.5259467, -122.687747,
color: Colors.purple));
mapView.zoomToFit(padding: 100);
});
compositeSubscription.add(sub);
sub = mapView.onLocationUpdated
.listen((location) => print("Location updated $location"));
compositeSubscription.add(sub);
sub = mapView.onTouchAnnotation
.listen((annotation) => print("annotation tapped"));
compositeSubscription.add(sub);
sub = mapView.onMapTapped
.listen((location) => print("Touched location $location"));
compositeSubscription.add(sub);
sub = mapView.onCameraChanged.listen((cameraPosition) =>
this.setState(() => this.cameraPosition = cameraPosition));
compositeSubscription.add(sub);
sub = mapView.onToolbarAction.listen((id) {
if (id == 1) {
_handleDismiss();
}
});
compositeSubscription.add(sub);
sub = mapView.onInfoWindowTapped.listen((marker) {
print("Info Window Tapped for ${marker.title}");
});
compositeSubscription.add(sub);
}
_handleDismiss() async {
double zoomLevel = await mapView.zoomLevel;
Location centerLocation = await mapView.centerLocation;
List<Marker> visibleAnnotations = await mapView.visibleAnnotations;
print("Zoom Level: $zoomLevel");
print("Center: $centerLocation");
print("Visible Annotation Count: ${visibleAnnotations.length}");
var uri = await staticMapProvider.getImageUriFromMap(mapView,
width: 900, height: 400);
setState(() => staticMapUri = uri);
mapView.dismiss();
compositeSubscription.cancel();
}
}
class CompositeSubscription {
Set<StreamSubscription> _subscriptions = new Set();
void cancel() {
for (var n in this._subscriptions) {
n.cancel();
}
this._subscriptions = new Set();
}
void add(StreamSubscription subscription) {
this._subscriptions.add(subscription);
}
void addAll(Iterable<StreamSubscription> subs) {
_subscriptions.addAll(subs);
}
bool remove(StreamSubscription subscription) {
return this._subscriptions.remove(subscription);
}
bool contains(StreamSubscription subscription) {
return this._subscriptions.contains(subscription);
}
List<StreamSubscription> toList() {
return this._subscriptions.toList();
}
}

View file

@ -5,7 +5,8 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'basicLocation.dart';
String gmapKey;
String appName = 'All Against Fire!';
String firesApiKey;
String appName = 'All Against The Fire!';
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
final List<BasicLocation> yourLocations = [];
final GetIt getIt = new GetIt();

View file

@ -11,7 +11,7 @@ class HomePage extends StatelessWidget {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
final _homeFont = const TextStyle(
fontSize: 40.0,
fontSize: 35.0,
fontWeight: FontWeight.w400,
// color: Colors.white,
);
@ -37,7 +37,7 @@ class HomePage extends StatelessWidget {
new Expanded(
child: new FractionallySizedBox(
alignment: FractionalOffset.bottomCenter,
heightFactor: 0.8,
heightFactor: 0.9,
child: new Image.asset('images/logo-200.png',
fit: BoxFit.fitHeight))),
new Expanded(
@ -46,7 +46,13 @@ class HomePage extends StatelessWidget {
heightFactor: 0.9,
child: new CenteredColumn(
children: <Widget>[
new Text(globals.appName, style: _homeFont),
new Padding(
padding: const EdgeInsets.all(10.0),
child: new Text(
globals.appName,
textAlign: TextAlign.center,
softWrap: true, style: _homeFont),
),
new SizedBox(height: 20.0),
new RoundedBtn.nav(
icon: Icons.whatshot,
@ -54,6 +60,13 @@ class HomePage extends StatelessWidget {
context: context,
route: ActiveFiresPage.routeName,
backColor: fires600),
new SizedBox(height: 20.0),
new RoundedBtn.nav(
icon: Icons.notifications_active,
text: 'Notify a fire',
context: context,
route: ActiveFiresPage.routeName,
backColor: fires600),
],
)))
])),

144
lib/leafletMap.dart Normal file
View file

@ -0,0 +1,144 @@
import 'package:flutter/material.dart';
import 'basicLocation.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map/plugin_api.dart';
import 'package:latlong/latlong.dart';
import 'colors.dart';
import 'mainDrawer.dart'
'';
class LeafletMap extends StatefulWidget {
final BasicLocation location;
final String title;
LeafletMap({@required this.title, @required this.location});
@override
_LeafletMapState createState() => _LeafletMapState(title: title, location: location);
}
class _LeafletMapState extends State<LeafletMap> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
final BasicLocation location;
final String title;
_LeafletMapState({@required this.title, @required this.location});
@override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
// drawer: new MainDrawer(context),
appBar: new AppBar(
title: new Text(title),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
},
child: const Icon(Icons.notifications_none),
backgroundColor: Colors.orange,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: new MapBottomAppBar(
menuCallback: () {
// _scaffoldKey.currentState.openDrawer();
},
fabLocation: FloatingActionButtonLocation.centerDocked,
showNotch: true,
bottomActions: <Widget>[
new Text('10 fires near you'),
SizedBox(width: 10.0)
]),
body: new FlutterMap(
options: new MapOptions(
center: new LatLng(this.location.lat, this.location.lon),
zoom: 13.0,
// THIS does not works as expected
// maxZoom: 6.0,
onPositionChanged: (positionCallback) {
print('$positionCallback');
}
),
layers: [
new TileLayerOptions(
maxZoom: 6.0,
urlTemplate: 'https://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',
additionalOptions: {
// 'opacity': '0.1',
'attribution': '&copy; <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors'
},
), /*
new TileLayerOptions(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
additionalOptions: {
// 'opacity': '0.1',
'attribution': '&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors'
},
), */
new MarkerLayerOptions(
markers: [
new Marker(
width: 80.0,
height: 80.0,
point: new LatLng(this.location.lat, this.location.lon),
builder: (ctx) =>
new Container(
child: new Image.asset('images/fire-marker-l.png'),
),
),
],
),
],
));
}
}
class MapBottomAppBar extends StatelessWidget {
const MapBottomAppBar(
{this.menuCallback,
this.fabLocation,
this.showNotch,
this.bottomActions});
final Color color = fires600;
final FloatingActionButtonLocation fabLocation;
final bool showNotch;
final VoidCallback menuCallback;
final List<Widget> bottomActions;
static final List<FloatingActionButtonLocation> kCenterLocations =
<FloatingActionButtonLocation>[
FloatingActionButtonLocation.centerDocked,
FloatingActionButtonLocation.centerFloat,
];
@override
Widget build(BuildContext context) {
final List<Widget> rowContents = <Widget>[
/* new IconButton(
icon: const Icon(Icons.menu),
onPressed: () {
menuCallback();
/* showModalBottomSheet<Null>(
context: context,
builder: (BuildContext context) => const _DemoDrawer(),
); */
},
), */
];
if (kCenterLocations.contains(fabLocation)) {
rowContents.add(
const Expanded(child: const SizedBox()),
);
}
rowContents.addAll(this.bottomActions);
return new BottomAppBar(
color: color,
hasNotch: showNotch,
child: new Row(children: rowContents),
);
}
}

View file

@ -1,19 +1,19 @@
import 'package:flutter/material.dart';
import 'firesApp.dart';
import 'package:comunes_flutter/comunes_flutter.dart';
import 'dart:async';
import 'globals.dart' as globals;
import 'basicLocationPersist.dart';
Future<String> getGMapKey() async {
Secret secret = await SecretLoader(secretPath: 'assets/private-settings.json')
.load('gmap_key');
return secret.apiKey;
Future<Map<String, dynamic>> loadSecrets() async {
return await SecretLoader(secretPath: 'assets/private-settings.json').load();
}
void main() {
getGMapKey().then((String gmapKey) {
globals.gmapKey = gmapKey;
loadSecrets().then((secrets) {
globals.firesApiKey = secrets['firesApiKey'];
globals.gmapKey = secrets['gmapKey'];
globals.prefs.then((prefs) {
loadYourLocations(prefs);

View file

@ -12,14 +12,16 @@ dependencies:
shared_preferences: "^0.4.2"
comunes_flutter:
path: /home/vjrj/dev/comunes_flutter
version: "^0.0.5"
version: "^0.0.7"
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: "^0.1.2"
map_view: "^0.0.12"
location: "^1.3.4"
flutter_google_places_autocomplete: "^0.0.4"
get_it: "^1.0.1+1"
flutter_map: "^0.0.1"
http: "^0.11.3+16"
simple_moment: "^0.0.3"
dev_dependencies:
flutter_test:
@ -45,6 +47,10 @@ flutter:
assets:
- images/logo-200.png
- assets/private-settings.json
- images/fire-marker-l.png
- images/fire-marker-m.png
- images/fire-marker-s.png
- images/fire-marker.png
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.