Newer
Older
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'dart:async';
import 'package:geolocator/geolocator.dart';
const AddEvent({Key? key}) : super(key: key);
@override
State<AddEvent> createState() => _AddEventPageState();
}
class _AddEventPageState extends State<AddEvent> {
late String long = "";
late String lat = "";
late String alt = "";
late StreamSubscription<Position> streamHandler; //For canceling GNSS stream on dispose
bool _labelValidate = false;
bool _descriptionValidate = false;
Future startGNSS() async {
debugPrint("Check Location Permission");
bool serviceStatus = false;
bool hasPermission = false;
serviceStatus = await Geolocator.isLocationServiceEnabled();
if(serviceStatus){
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
}else if(permission == LocationPermission.deniedForever){
debugPrint('Location permissions are permanently denied');
if(hasPermission){
debugPrint('Location permissions granted');
if(mounted){
setState(() {
//refresh the UI
});}
debugPrint('Starting location stream');
streamHandler = Geolocator.getPositionStream(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 0,
)).listen((Position position) {
debugPrint('Get Location: Lat:' + position.latitude.toString() +
' Long:' + position.longitude.toString() +
' Alt:' + position.altitude.toString());
long = position.longitude.toString();
lat = position.latitude.toString();
alt = position.altitude.toString();
accuracy = position.accuracy;
if (syncGNSSData == true) {
if(mounted){
setState(() {
//refresh UI on update
});}
}
});
debugPrint("GPS Service is not enabled, turn on GPS location");
setState(() {
//refresh the UI
});}
@override
void dispose() {
try {
streamHandler.cancel();
debugPrint('Cancel location stream');
}catch(e){
debugPrint('Canceling location stream failed');
}
super.dispose();
}
bool _validateInput(){
final EventStoreInstance eventsStore = EventStoreInstance();
if (RegExp(r'^[a-z A-Z . \- 0-9 , ( ) + - _ :]+$').hasMatch(
eventsStore.currentEvent.label)) {
if (RegExp(r'^[a-z A-Z . \- 0-9 , ( ) + - _ :]+$').hasMatch(
eventsStore.currentEvent.description)) {
return true;
}
}
return false;
}
final EventStoreInstance eventsStore = EventStoreInstance();
eventsStore.currentEvent.status = "PENDING";
eventsStore.events.add(
eventsStore.currentEvent.id,
eventsStore.currentEvent.urn,
eventsStore.currentEvent.label,
eventsStore.currentEvent.type,
eventsStore.currentEvent.description,
eventsStore.currentEvent.status,
eventsStore.currentEvent.startDate,
eventsStore.currentEvent.endDate,
eventsStore.currentEvent.latitude,
eventsStore.currentEvent.longitude,
eventsStore.currentEvent.elevation
//TODO: add field validators for freetext fields. Check allowed characters in sensor.awi.de
@override
Widget build(BuildContext context) {
/* Get singletons to access relevant data here.*/
final EventStoreInstance eventsStore = EventStoreInstance();
final ConfigurationStoreInstance configuration = ConfigurationStoreInstance();
// Update current event coordinates from GNSS stream
eventsStore.currentEvent.latitude = lat;
eventsStore.currentEvent.longitude = long;
eventsStore.currentEvent.elevation = alt;
var date = DateTime.now().toUtc();
eventsStore.currentEvent.startDate = '$date';
eventsStore.currentEvent.endDate = '$date';
if(accuracy == 0.0){
gnssStatusText = "No-Fix";
else{
gnssStatusText = "Precision: "+ accuracy.toStringAsFixed(2) +"m";
}
gnssStatusText = "GNSS Disabled"; // Just display existing event coordinates
if (configuration.initialized == true) {
return Scaffold(
appBar: AppBar(title: const Text("Add Event")),
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
body: SingleChildScrollView(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 5.0),
child:
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
const SizedBox(height: 15.0),
TextFormField(
initialValue: eventsStore.currentEvent.label,
autovalidateMode: AutovalidateMode.always,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Label',
),
onChanged: (value){
eventsStore.currentEvent.label = value;
setState(() {});
},
validator: (value) {
if (!RegExp(r'^[a-z A-Z . \- 0-9 , ( ) + - _ :]+$').hasMatch(
value!)) {
_labelValidate = false;
return "Only: a-z , A-Z , _ , 0-9 , ,(Comma) , ( , ) , + , - , . , :";
} else {
_labelValidate = true;
//eventsStore.currentEvent.label = value;
return null; // Entered Text is valid
}
},
),
const SizedBox(height: 15.0),
DropdownButtonFormField(
value: eventsStore.currentEvent.type,
isExpanded: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Event Type',
),
items:
configuration.eventTypes.map((EventType event) {
return DropdownMenuItem(
value: event.name,
child: Text(event.name),
);
}).toList(),
onChanged: (value) {
eventsStore.currentEvent.type = value.toString();
}
),
const SizedBox(height: 15.0),
DropdownButtonFormField(
value: eventsStore.currentEvent.urn,
isExpanded: true,
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
items:
configuration.devices.map((Device device) {
return DropdownMenuItem(
value: device.urn,
child: Text(device.urn),
);
}).toList(),
onChanged: (value) {
eventsStore.currentEvent.urn = value.toString();
eventsStore.currentEvent.id =
configuration.getDeviceIdFromUrn(value.toString());
}
),
const SizedBox(height: 15.0),
TextFormField(
initialValue: eventsStore.currentEvent.description,
autovalidateMode: AutovalidateMode.always,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Description'
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
onChanged: (value){
eventsStore.currentEvent.description = value;
setState(() {});
},
validator: (value) {
if (!RegExp(r'^[a-z A-Z . \- 0-9 , ( ) + - _ :]+$').hasMatch(
value!)) {
_descriptionValidate = false;
return "Only: a-z , A-Z , _ , 0-9 , ,(Comma) , ( , ) , + , - , . , :";
} else {
_descriptionValidate = true;
//eventsStore.currentEvent.label = value;
return null; // Entered Text is valid
}
},
),
const SizedBox(height: 15.0),
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Flexible(child:
TextFormField(
controller: TextEditingController(
text: eventsStore.currentEvent.startDate),
readOnly: true,
decoration: const InputDecoration(
labelText: 'Timestamp',
//helperText: '', //Adds some space below field
border: OutlineInputBorder(),
),
onTap: () {
DatePicker.showDateTimePicker(context,
showTitleActions: true,
onConfirm: (date) {
//Only one field for start and end date.
eventsStore.currentEvent.startDate = '$date';
eventsStore.currentEvent.endDate = '$date';
debugPrint('Date set to : $date');
setState(() {});
},
currentTime: DateTime.now().toUtc(),
locale: LocaleType.en);
},
),
),
ElevatedButton(
onPressed: () {
var date = DateTime.now().toUtc();
eventsStore.currentEvent.startDate = '$date';
eventsStore.currentEvent.endDate = '$date';
debugPrint('Date set to : ' +
eventsStore.currentEvent.endDate.toString());
setState(() {});
},
child: const Text('Now'),
),
]
const SizedBox(height: 15.0),
TextFormField(
readOnly: false,
enabled: !syncGNSSData,
controller: TextEditingController(
text: eventsStore.currentEvent.latitude.toString()),
decoration: const InputDecoration(
labelText: 'Latitude',
border: OutlineInputBorder(),
),
onChanged: (value) {
eventsStore.currentEvent.latitude = value;
}
),
const SizedBox(height: 15.0),
TextFormField(
readOnly: false,
enabled: !syncGNSSData,
controller: TextEditingController(
text: eventsStore.currentEvent.longitude.toString()),
decoration: const InputDecoration(
labelText: 'Longitude',
border: OutlineInputBorder(),
),
onChanged: (value) {
eventsStore.currentEvent.longitude = value;
}
const SizedBox(height: 15.0),
TextFormField(
readOnly: false,
enabled: !syncGNSSData,
controller: TextEditingController(
text: eventsStore.currentEvent.elevation.toString()),
decoration: const InputDecoration(
labelText: 'Elevation',
border: OutlineInputBorder(),
),
onChanged: (value) {
eventsStore.currentEvent.elevation = value;
}
bottomNavigationBar: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(gnssStatusText),
const SizedBox(width: 10),
Switch(
value: syncGNSSData,
onChanged: (value) {
syncGNSSData = value;
debugPrint('Switched to:' + syncGNSSData.toString());
setState(() {
//refresh the UI
});
},
const SizedBox(width: 50),
Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: _validateInput() ?
FloatingActionButton(
onPressed: () {
_storeCurrentEvent();
HapticFeedback.vibrate();
},
tooltip: 'Add Event',
child: const Icon(Icons.check),
) :
FloatingActionButton(
enableFeedback: false,
backgroundColor: Colors.grey,
onPressed: () {
},
tooltip: 'Correct Inputs before adding the Event',
//child: const Icon(Icons.check),
)
],
),
);
}else {
return Scaffold(
appBar: AppBar(title: const Text("Add Event")),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.end,
children: const <Widget>[
Text(
' Visit Configuration first.',
style: TextStyle(fontSize: 20)
),
],
),
);
}