mirror of
https://github.com/TrentSPalmer/libre_gps_parser.git
synced 2025-08-23 04:23:57 -07:00
initial commit
This commit is contained in:
156
lib/database_helper.dart
Normal file
156
lib/database_helper.dart
Normal file
@@ -0,0 +1,156 @@
|
||||
import 'dart:io';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class DatabaseHelper {
|
||||
|
||||
static final _databaseName = "LnLShare.db";
|
||||
static final _databaseVersion = 1;
|
||||
|
||||
static final table = 'gmaplocations';
|
||||
static final weatherTable = 'weather';
|
||||
|
||||
static final columnMapLocation = 'mapLocation';
|
||||
static final columnLatLong = 'latLong';
|
||||
static final columnLnlTime = 'lnlTime';
|
||||
static final columnViewTime = 'viewTime';
|
||||
static final columnElev = 'elev';
|
||||
static final columnElevTime = 'elevTime';
|
||||
static final columnWeatherID = 'weatherID';
|
||||
|
||||
static final columnWeatherWeatherID = 'weatherID';
|
||||
static final columnWeather = 'weather';
|
||||
static final columnWeatherForecast = 'weatherForecast';
|
||||
|
||||
// make this a singleton class
|
||||
DatabaseHelper._privateConstructor();
|
||||
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
|
||||
|
||||
// only have a single app-wide reference to the database
|
||||
static Database _database;
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database;
|
||||
// lazily instantiate the db the first time it is accessed
|
||||
_database = await _initDatabase();
|
||||
return _database;
|
||||
}
|
||||
|
||||
// this opens the database (and creates it if it doesn't exist)
|
||||
_initDatabase() async {
|
||||
Directory documentsDirectory = await getApplicationDocumentsDirectory();
|
||||
String path = join(documentsDirectory.path, _databaseName);
|
||||
return await openDatabase(path,
|
||||
version: _databaseVersion,
|
||||
onCreate: _onCreate);
|
||||
}
|
||||
|
||||
// SQL code to create the database table
|
||||
Future _onCreate(Database db, int version) async {
|
||||
await db.execute('''
|
||||
CREATE TABLE $table (
|
||||
$columnMapLocation VARCHAR UNIQUE,
|
||||
$columnLatLong TEXT,
|
||||
$columnLnlTime INT,
|
||||
$columnViewTime INT,
|
||||
$columnElev INT,
|
||||
$columnElevTime INT,
|
||||
$columnWeatherID INT
|
||||
)
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE TABLE $weatherTable (
|
||||
$columnWeatherWeatherID INT UNIQUE,
|
||||
$columnWeather TEXT,
|
||||
$columnWeatherForecast TEXT
|
||||
)
|
||||
''');
|
||||
}
|
||||
|
||||
Future<int> insert(Map<String, dynamic> row) async {
|
||||
Database db = await instance.database;
|
||||
return await db.insert(table, row);
|
||||
}
|
||||
|
||||
Future<int> insertWeatherRow(Map<String, dynamic> row) async {
|
||||
Database db = await instance.database;
|
||||
return await db.insert(weatherTable, row);
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> queryAllRows() async {
|
||||
Database db = await instance.database;
|
||||
return await db.query(table);
|
||||
}
|
||||
|
||||
Future<int> queryRowCount() async {
|
||||
Database db = await instance.database;
|
||||
return Sqflite.firstIntValue(await db.rawQuery('SELECT COUNT(*) FROM $table'));
|
||||
}
|
||||
|
||||
Future<int> queryRowExists(String mapLocation) async {
|
||||
Database db = await instance.database;
|
||||
return Sqflite.firstIntValue(await db.rawQuery('SELECT EXISTS (SELECT $columnMapLocation FROM $table WHERE $columnMapLocation=\'$mapLocation\')'));
|
||||
}
|
||||
|
||||
Future<int> queryWeatherIDExists(int weatherID) async {
|
||||
Database db = await instance.database;
|
||||
return Sqflite.firstIntValue(await db.rawQuery('SELECT EXISTS (SELECT $columnWeatherWeatherID FROM $weatherTable WHERE $columnWeatherWeatherID=\'$weatherID\')'));
|
||||
}
|
||||
|
||||
Future<String> queryNewestMapLocation() async {
|
||||
Database db = await instance.database;
|
||||
List<Map> result = await db.rawQuery('SELECT $columnMapLocation FROM $table ORDER BY $columnViewTime DESC LIMIT 1');
|
||||
return (result.length == 0) ? 'Plataea\nGreece\nhttps://maps.app.goo.gl/1NW9z': result[0]['mapLocation'];
|
||||
}
|
||||
|
||||
Future<List<String>> sortedMapLocations() async {
|
||||
Database db = await instance.database;
|
||||
var result = await db.rawQuery('SELECT $columnMapLocation FROM $table ORDER BY $columnViewTime DESC');
|
||||
List<String> result_list = new List<String>();
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
result_list.add(result[i]['mapLocation']);
|
||||
}
|
||||
return result_list;
|
||||
}
|
||||
|
||||
Future<String> queryLatNLong(String mapLocation) async {
|
||||
Database db = await instance.database;
|
||||
List<Map> result = await db.rawQuery('SELECT $columnLatLong FROM $table WHERE $columnMapLocation = ?',[mapLocation]);
|
||||
return (result[0]['latLong'] == null) ? 'NA' : result[0]['latLong'];
|
||||
}
|
||||
|
||||
Future<String> queryWeather(int weatherID) async {
|
||||
Database db = await instance.database;
|
||||
List<Map> result = await db.rawQuery('SELECT $columnWeather FROM $weatherTable WHERE $columnWeatherWeatherID = ?',[weatherID]);
|
||||
return result[0]['weather'];
|
||||
}
|
||||
|
||||
Future<int> queryElevation(String mapLocation) async {
|
||||
Database db = await instance.database;
|
||||
List<Map> result = await db.rawQuery('SELECT $columnElev FROM $table WHERE $columnMapLocation = ?',[mapLocation]);
|
||||
return result[0]['elev'];
|
||||
}
|
||||
|
||||
Future<int> queryWeatherID(String mapLocation) async {
|
||||
Database db = await instance.database;
|
||||
List<Map> result = await db.rawQuery('SELECT $columnWeatherID FROM $table WHERE $columnMapLocation = ?',[mapLocation]);
|
||||
return result[0]['weatherID'];
|
||||
}
|
||||
|
||||
Future<int> update(Map<String, dynamic> row) async {
|
||||
Database db = await instance.database;
|
||||
String mapLocation = row[columnMapLocation];
|
||||
return await db.update(table, row, where: '$columnMapLocation = ?', whereArgs: [mapLocation]);
|
||||
}
|
||||
|
||||
Future<int> updateWeathTbl(Map<String, dynamic> row) async {
|
||||
Database db = await instance.database;
|
||||
int weatherID = row[columnWeatherWeatherID];
|
||||
return await db.update(weatherTable, row, where: '$columnWeatherWeatherID = ?', whereArgs: [weatherID]);
|
||||
}
|
||||
|
||||
Future<int> delete(String ml) async {
|
||||
Database db = await instance.database;
|
||||
return await db.delete(table, where: '$columnMapLocation = ?', whereArgs: [ml]);
|
||||
}
|
||||
}
|
144
lib/global_helper_functions.dart
Normal file
144
lib/global_helper_functions.dart
Normal file
@@ -0,0 +1,144 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'database_helper.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
final EdgeInsets myBoxPadding = EdgeInsets.all(10.0);
|
||||
final Color navy = Color(0xff00293C);
|
||||
final Color peacock_blue = Color(0xff1e656d);
|
||||
final Color ivory = Color(0xfff1f3ce);
|
||||
final Color candy_apple = Color(0xfff62a00);
|
||||
final String weatherApiUrlPrefix = 'https://api.openweathermap.org/data/2.5/weather?';
|
||||
final String weatherForecastApiUrlPrefix = 'https://api.openweathermap.org/data/2.5/forecast?';
|
||||
|
||||
Future<String> getWeather(String mapLocation, String lat_Long) async {
|
||||
// https://dragosholban.com/2018/07/01/how-to-build-a-simple-weather-app-in-flutter
|
||||
final dbHelper = DatabaseHelper.instance;
|
||||
String weatherApiID = await getPreferenceOpenWeatherMapApiKey();
|
||||
if (weatherApiID == 'none?') { return null;}
|
||||
else {
|
||||
int weatherID = await dbHelper.queryWeatherID(mapLocation);
|
||||
if (weatherID == null) {
|
||||
List<String> latLong = lat_Long.split(',');
|
||||
String weatherApiUrl = '${weatherApiUrlPrefix}lat=${latLong[0]}&lon=${latLong[1]}&units=imperial&appid=${weatherApiID}';
|
||||
Response response = await get(weatherApiUrl);
|
||||
if (response.statusCode == 200) {
|
||||
Map<String, dynamic> responseJson = jsonDecode(response.body);
|
||||
weatherID = responseJson['id'];
|
||||
Map<String, dynamic> row = {
|
||||
DatabaseHelper.columnMapLocation: mapLocation,
|
||||
DatabaseHelper.columnWeatherID: weatherID
|
||||
};
|
||||
await dbHelper.update(row);
|
||||
Map<String, dynamic> row2 = {
|
||||
DatabaseHelper.columnWeatherWeatherID: weatherID,
|
||||
DatabaseHelper.columnWeather: response.body
|
||||
};
|
||||
int weatherIDExists = await dbHelper.queryWeatherIDExists(weatherID);
|
||||
if (weatherIDExists == 0) {
|
||||
dbHelper.insertWeatherRow(row2);
|
||||
} else {
|
||||
dbHelper.updateWeathTbl(row2);
|
||||
}
|
||||
return response.body;
|
||||
}
|
||||
} else {
|
||||
String weather = await dbHelper.queryWeather(weatherID);
|
||||
return(weather);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
BoxDecoration myBoxDecoration(Color color) {
|
||||
return BoxDecoration(
|
||||
color: color,
|
||||
border: Border.all(
|
||||
width: 2.0,
|
||||
),
|
||||
borderRadius: new BorderRadius.all(new Radius.circular(6.0)),
|
||||
boxShadow: [
|
||||
new BoxShadow(
|
||||
offset: new Offset(2.0, 1.0),
|
||||
blurRadius: 1.0,
|
||||
spreadRadius: 1.0,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
int newTimeStamp() {
|
||||
DateTime date = new DateTime.now();
|
||||
return (date.millisecondsSinceEpoch / 1000).floor();
|
||||
}
|
||||
|
||||
Future<String> parseMapUrl(String mapUrl) async {
|
||||
Response response = await get(mapUrl);
|
||||
RegExp gmapUrl = new RegExp(r'https://www.google.com/(maps/preview)/(place)/([^/]*)/([^/]*)/data');
|
||||
String mapInfo = response.body;
|
||||
Match match = gmapUrl.firstMatch(mapInfo);
|
||||
String subMapInfo = match.group(4);
|
||||
RegExp subGmapUrl = new RegExp(r'@([^,]*,[^,]*),([^,]*,[^,]*)');
|
||||
Match subMatch = subGmapUrl.firstMatch(subMapInfo);
|
||||
return subMatch.group(1);
|
||||
}
|
||||
|
||||
Future<String> getPreferenceElevationServer() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String elevationServer = prefs.getString("elevationServer") ?? "https://example.com";
|
||||
return elevationServer;
|
||||
}
|
||||
|
||||
Future<bool> setPreferenceElevationServer(String elevationServer) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setString("elevationServer",elevationServer);
|
||||
return prefs.commit();
|
||||
}
|
||||
|
||||
Future<String> getPreferenceOpenWeatherMapApiKey() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
String apiKey = prefs.getString("openWeatherMapApiKey") ?? "none?";
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
Future<bool> setPreferenceOpenWeatherMapApiKey(String apiKey) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
prefs.setString("openWeatherMapApiKey",apiKey);
|
||||
return prefs.commit();
|
||||
}
|
||||
|
||||
Future<int> fetchElevation(String mapLocation) async {
|
||||
final dbHelper = DatabaseHelper.instance;
|
||||
String latLong = await dbHelper.queryLatNLong(mapLocation);
|
||||
if (latLong == 'NA') { return null;}
|
||||
else {
|
||||
String elevationServer = await getPreferenceElevationServer();
|
||||
String elevationApiUrl = elevationServer + '/api/v1/lookup\?locations\=' + latLong;
|
||||
Response response = await get(elevationApiUrl);
|
||||
if (response.statusCode == 200) {
|
||||
Map<String, dynamic> responseJson = jsonDecode(response.body);
|
||||
int elevation = responseJson['results'][0]['elevation'];
|
||||
return elevation;
|
||||
} else {return null;}
|
||||
}
|
||||
}
|
||||
|
||||
String convertCoordinates(String latNLong) {
|
||||
List<String> latLong = latNLong.split(',');
|
||||
List<String> lat = latLong[0].split('.');
|
||||
List<String> long = latLong[1].split('.');
|
||||
String latMinSec = getMinSec(lat[1]);
|
||||
String longMinSec = getMinSec(long[1]);
|
||||
String gpsDMS = lat[0] + '\u00B0 ' + latMinSec + ',' + long[0] + '\u00B0 ' + longMinSec;
|
||||
return gpsDMS;
|
||||
}
|
||||
|
||||
String getMinSec(String numString) {
|
||||
String numString_x = '0.' + numString;
|
||||
double num = double.parse(numString_x);
|
||||
int mins = (num * 100 * 0.6).floor();
|
||||
double secs = ((((num * 100 * 0.6) % 1) * 100000 * .6).round() / 1000);
|
||||
String minSecs = mins.toString() + '\' ' + secs.toString();
|
||||
return minSecs;
|
||||
}
|
321
lib/main.dart
Normal file
321
lib/main.dart
Normal file
@@ -0,0 +1,321 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'global_helper_functions.dart';
|
||||
import 'database_helper.dart';
|
||||
import 'weather.dart';
|
||||
import 'settings.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
void main() => runApp(MainApp());
|
||||
|
||||
class MainApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new MaterialApp(
|
||||
title: 'Lat\'n Long Share',
|
||||
theme: new ThemeData(
|
||||
primaryColor: navy,
|
||||
),
|
||||
home: LatNLong(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LatNLong extends StatefulWidget {
|
||||
@override
|
||||
_LatNLongState createState() => new _LatNLongState();
|
||||
}
|
||||
|
||||
class _LatNLongState extends State<LatNLong> {
|
||||
// https://stackoverflow.com/a/32437518 <- to here for time zone api info
|
||||
final dbHelper = DatabaseHelper.instance;
|
||||
static const platform = const MethodChannel('app.channel.shared.data');
|
||||
RegExp gmapExp = new RegExp(r'(https://maps.app.goo.gl/)(.*$)');
|
||||
String widgetMapLocation = "none";
|
||||
String latnLong = "none";
|
||||
String latnLongDMS = "none";
|
||||
int elevation;
|
||||
int feetElevation;
|
||||
Map<String, dynamic> _weather = {
|
||||
"id":0,
|
||||
"weather":[
|
||||
{
|
||||
"description":"none",
|
||||
"icon":"none"
|
||||
}
|
||||
],
|
||||
"main": {
|
||||
"temp":0,
|
||||
"pressure":0,
|
||||
"humidity":0,
|
||||
"temp_min":0,
|
||||
"temp_max":0
|
||||
},
|
||||
"visibility":0,
|
||||
"wind": {
|
||||
"speed":0,
|
||||
"deg":0
|
||||
},
|
||||
"dt":0,
|
||||
"sunrise":0,
|
||||
"sunset":0
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
updateState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Scaffold(
|
||||
backgroundColor: peacock_blue,
|
||||
appBar: new AppBar(
|
||||
leading: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.settings), onPressed: _settings);
|
||||
},
|
||||
),
|
||||
title: new Text('Lat N Long Share'),
|
||||
actions: <Widget>[
|
||||
new IconButton(icon: const Icon(Icons.list), onPressed: _pushSaved),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: new Container(
|
||||
padding: EdgeInsets.all(20.0),
|
||||
child: new Wrap(
|
||||
spacing: 20.0,
|
||||
runSpacing: 20.0,
|
||||
alignment: WrapAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: myBoxPadding,
|
||||
decoration: myBoxDecoration(ivory),
|
||||
child: Text(
|
||||
'DD / DMS: \n(${this.latnLong})\n(${this.latnLongDMS})' ,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: myBoxPadding,
|
||||
decoration: myBoxDecoration(ivory),
|
||||
child: Text(
|
||||
this.widgetMapLocation,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: myBoxPadding,
|
||||
decoration: myBoxDecoration(ivory),
|
||||
child: Text(
|
||||
'elevation: ${this.feetElevation.toString()} feet, ${this.elevation.toString()} meters',
|
||||
),
|
||||
),
|
||||
Weather(weather: this._weather,),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _settings() {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => Settings()),
|
||||
);
|
||||
}
|
||||
|
||||
void _pushSaved() async {
|
||||
List<String> sorted_Map_Locations = await dbHelper.sortedMapLocations();
|
||||
await Navigator.of(context).push(
|
||||
new MaterialPageRoute<void>(
|
||||
builder: (BuildContext context) {
|
||||
return new Scaffold(
|
||||
backgroundColor: peacock_blue,
|
||||
appBar: new AppBar(
|
||||
title: const Text('Previous Locations'),
|
||||
),
|
||||
body: _buildHistory(sorted_Map_Locations),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHistory(List<String> sorted_Map_Locations) {
|
||||
return new ListView.builder(
|
||||
itemCount: sorted_Map_Locations.length,
|
||||
itemBuilder: (BuildContext ctxt, int i) {
|
||||
return new InkWell(
|
||||
onTap: () {
|
||||
selectMapLocation(sorted_Map_Locations[i]);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: new Card(
|
||||
margin: EdgeInsets.all(4.0),
|
||||
color: Colors.black,
|
||||
child: new Card(
|
||||
margin: EdgeInsets.all(4.0),
|
||||
color: ivory,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
sorted_Map_Locations[i],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: new Icon(
|
||||
Icons.arrow_right,
|
||||
size: 50.0,
|
||||
color: candy_apple,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateState() async {
|
||||
var sharedData = await platform.invokeMethod("getSharedText");
|
||||
if (sharedData != null && sharedData is String) {
|
||||
if (gmapExp.hasMatch(sharedData)) {
|
||||
setState(() {
|
||||
this.widgetMapLocation = sharedData;
|
||||
});
|
||||
}
|
||||
} else if (sharedData == null) {
|
||||
sharedData = await dbHelper.queryNewestMapLocation();
|
||||
if (sharedData != null && sharedData is String) {
|
||||
setState(() {
|
||||
this.widgetMapLocation = sharedData;
|
||||
});
|
||||
}
|
||||
}
|
||||
await _Create_Row_If_Needed(sharedData);
|
||||
await _populateLatNLong(sharedData);
|
||||
}
|
||||
|
||||
Future<void> _populateWeather(String mapLocation, String latLong) async {
|
||||
String weather = await getWeather(mapLocation,latLong);
|
||||
if (weather != null) {
|
||||
Map<String, dynamic> weatherJson = jsonDecode(weather);
|
||||
if (weatherJson != this._weather) {
|
||||
setState(() {
|
||||
this._weather = weatherJson;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _populateElevation(String mapLocation) async {
|
||||
await dbHelper.queryElevation(mapLocation).then((int elev) {
|
||||
if (elev != this.elevation) {
|
||||
if (elev != null) {
|
||||
setState(() {
|
||||
this.elevation = elev;
|
||||
this.feetElevation = (elev * 3.28084).round();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (elev == null) {
|
||||
final int timeStamp = newTimeStamp();
|
||||
updateElevation(timeStamp, mapLocation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> updateElevation(int timeStamp, String mapLocation) async {
|
||||
await fetchElevation(mapLocation).then((int elev) {
|
||||
if (elev != null) {
|
||||
setState(() {
|
||||
this.elevation = elev;
|
||||
this.feetElevation = (elev * 3.28084).round();
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
this.elevation = null;
|
||||
this.feetElevation = null;
|
||||
});
|
||||
|
||||
}
|
||||
Map<String, dynamic> row = {
|
||||
DatabaseHelper.columnMapLocation: mapLocation,
|
||||
DatabaseHelper.columnElevTime: timeStamp,
|
||||
DatabaseHelper.columnElev: elev
|
||||
};
|
||||
dbHelper.update(row);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Future<void> _populateLatNLong(String mapLocation) async {
|
||||
await dbHelper.queryLatNLong(mapLocation).then((String lat_long) {
|
||||
if ((lat_long != this.latnLong) && (lat_long != 'NA')) {
|
||||
_populateElevation(mapLocation);
|
||||
_populateWeather(mapLocation, lat_long);
|
||||
setState(() {
|
||||
this.latnLong = lat_long;
|
||||
this.latnLongDMS = convertCoordinates(lat_long);
|
||||
});
|
||||
}
|
||||
if (lat_long == 'NA') {
|
||||
final int timeStamp = newTimeStamp();
|
||||
updateLatNLong(timeStamp, mapLocation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> updateLatNLong(int timeStamp, String mapLocation) async {
|
||||
String mapUrl = gmapExp.stringMatch(mapLocation);
|
||||
await parseMapUrl(mapUrl).then((String lat_long) {
|
||||
setState(() {
|
||||
this.latnLong = lat_long;
|
||||
this.latnLongDMS = convertCoordinates(lat_long);
|
||||
});
|
||||
Map<String, dynamic> row = {
|
||||
DatabaseHelper.columnMapLocation: mapLocation,
|
||||
DatabaseHelper.columnLnlTime: timeStamp,
|
||||
DatabaseHelper.columnLatLong: lat_long
|
||||
};
|
||||
dbHelper.update(row);
|
||||
updateElevation(timeStamp, mapLocation);
|
||||
_populateWeather(mapLocation, lat_long);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> selectMapLocation(String mapLocation) async {
|
||||
int time_Stamp = newTimeStamp();
|
||||
Map<String, dynamic> row = {
|
||||
DatabaseHelper.columnMapLocation: mapLocation,
|
||||
DatabaseHelper.columnViewTime: time_Stamp
|
||||
};
|
||||
setState(() {
|
||||
this.widgetMapLocation = mapLocation;
|
||||
});
|
||||
await dbHelper.update(row);
|
||||
await _populateLatNLong(mapLocation);
|
||||
}
|
||||
|
||||
Future<void> _Create_Row_If_Needed(String mapLocation) async {
|
||||
final int rowExists = await dbHelper.queryRowExists(mapLocation);
|
||||
final int timeStamp = newTimeStamp();
|
||||
if (rowExists == 0) {
|
||||
Map<String, dynamic> row = {
|
||||
DatabaseHelper.columnMapLocation: mapLocation,
|
||||
DatabaseHelper.columnViewTime: timeStamp
|
||||
};
|
||||
final id = await dbHelper.insert(row);
|
||||
}
|
||||
}
|
||||
}
|
153
lib/settings.dart
Normal file
153
lib/settings.dart
Normal file
@@ -0,0 +1,153 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'global_helper_functions.dart';
|
||||
|
||||
class Settings extends StatefulWidget {
|
||||
@override
|
||||
_SettingsState createState() => new _SettingsState();
|
||||
}
|
||||
|
||||
class _SettingsState extends State<Settings> {
|
||||
String elevationServer = "none";
|
||||
String openWeatherMapKey = "none";
|
||||
String shortOWMAK = "none";
|
||||
final _elevationServerController = TextEditingController();
|
||||
final _oWMKController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
updateState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new Scaffold(
|
||||
backgroundColor: peacock_blue,
|
||||
appBar: new AppBar(
|
||||
title: const Text('Settings'),
|
||||
),
|
||||
body: new ListView(
|
||||
children: <Widget> [
|
||||
new Container(
|
||||
padding: myBoxPadding,
|
||||
decoration: myBoxDecoration(ivory),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Open-Elevation Api Server to Use',
|
||||
),
|
||||
Text(
|
||||
'Current Value: ' + this.elevationServer,
|
||||
),
|
||||
TextField(
|
||||
controller: _elevationServerController,
|
||||
decoration: InputDecoration(
|
||||
hintText: this.elevationServer,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(
|
||||
top: 20.0,
|
||||
bottom: 5.0,
|
||||
),
|
||||
child: RaisedButton.icon(
|
||||
label: Text(
|
||||
"Update Elevation Server",
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.refresh,
|
||||
size: 50.0,
|
||||
),
|
||||
color: candy_apple,
|
||||
onPressed: () { _updateElevationServer(); },
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
new Container(
|
||||
padding: myBoxPadding,
|
||||
decoration: myBoxDecoration(ivory),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Open Weather Map Api Key to Use',
|
||||
),
|
||||
Text(
|
||||
'Current Value: ${this.shortOWMAK}...',
|
||||
),
|
||||
TextField(
|
||||
controller: _oWMKController,
|
||||
decoration: InputDecoration(
|
||||
hintText: '${this.shortOWMAK}...',
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(
|
||||
top: 20.0,
|
||||
bottom: 5.0,
|
||||
),
|
||||
child: RaisedButton.icon(
|
||||
label: Text(
|
||||
"Update ... Api Key",
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.refresh,
|
||||
size: 50.0,
|
||||
),
|
||||
color: candy_apple,
|
||||
onPressed: () { _updateOpenWeatherMapApiKey(); },
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateState() async {
|
||||
String evServer = await getPreferenceElevationServer();
|
||||
String oWMK = await getPreferenceOpenWeatherMapApiKey();
|
||||
if ((evServer != this.elevationServer) || (oWMK != this.openWeatherMapKey)) {
|
||||
setState((){
|
||||
this.elevationServer = evServer;
|
||||
this.openWeatherMapKey = oWMK;
|
||||
this.shortOWMAK = oWMK.substring(0,5);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _updateOpenWeatherMapApiKey() {
|
||||
String oWMK = _oWMKController.text;
|
||||
if (oWMK.length > 0) {
|
||||
setPreferenceOpenWeatherMapApiKey(oWMK).then((bool committed) {
|
||||
if (oWMK != this.openWeatherMapKey) {
|
||||
setState((){
|
||||
this.openWeatherMapKey = oWMK;
|
||||
this.shortOWMAK = oWMK.substring(0,5);
|
||||
});
|
||||
}
|
||||
});
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
void _updateElevationServer() {
|
||||
String elevServer = _elevationServerController.text;
|
||||
RegExp urlValidator = new RegExp(r'^http[s]?://.+$');
|
||||
if (urlValidator.hasMatch(elevServer)) {
|
||||
setPreferenceElevationServer(elevServer).then((bool committed) {
|
||||
if (elevServer != this.elevationServer) {
|
||||
setState((){
|
||||
this.elevationServer = elevServer;
|
||||
});
|
||||
}
|
||||
});
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
34
lib/weather.dart
Normal file
34
lib/weather.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'global_helper_functions.dart';
|
||||
|
||||
|
||||
class Weather extends StatefulWidget {
|
||||
|
||||
Map<String, dynamic> weather;
|
||||
|
||||
Weather({Key key, this.weather}) : super(key: key);
|
||||
|
||||
@override
|
||||
_WeatherState createState() => new _WeatherState();
|
||||
}
|
||||
|
||||
class _WeatherState extends State<Weather> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: myBoxPadding,
|
||||
decoration: myBoxDecoration(ivory),
|
||||
child: Wrap(
|
||||
spacing: 10.0,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Current Weather Conditions: ${widget.weather['weather'][0]['description']}',
|
||||
),
|
||||
Text(
|
||||
'Weather location: ${widget.weather['id']}',
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user