Commit ce808319 authored by Nicolas Richard Walter Boeckh's avatar Nicolas Richard Walter Boeckh 💬
Browse files

Moving files to hierarchical structure, UI tweaks

- Graph : Added Axis Titles
- NavBar : Migrated to "cicular_bottom_navigation"
- Battery Indicator : Rounded corners + Color lerping
- Data Tile :  resized text
parent cb6b9f53
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"macos":[{"name":"shared_preferences_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_macos-0.0.1+8\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2020-08-21 09:20:35.704809","version":"1.21.0-10.0.pre.212"} {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"macos":[{"name":"shared_preferences_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_macos-0.0.1+8\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2020-08-26 17:00:48.008588","version":"1.22.0-2.0.pre.18"}
\ No newline at end of file \ No newline at end of file
import 'package:carousel_slider/carousel_slider.dart'; import 'package:carousel_slider/carousel_slider.dart';
import 'package:circular_bottom_navigation/circular_bottom_navigation.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:logair_application/ui/routes/home.dart'; import 'package:logair_application/ui/routes/home.dart';
...@@ -13,10 +14,24 @@ class HomeController { ...@@ -13,10 +14,24 @@ class HomeController {
/// The controller for the [CarouselSlider]. /// The controller for the [CarouselSlider].
PageController _pageController; PageController _pageController;
/// The controller for the [CircularBottomNavigation]
CircularBottomNavigationController _navigationController;
/// Sets the [PageController] for the [CarouselSlider]
set carouselController(PageController carouselController) => this._pageController = carouselController; set carouselController(PageController carouselController) => this._pageController = carouselController;
get carouselController => this._pageController; /// Sets the [CircularBottomNavigationController] for the [CircularBottomNavigation]
set navigationController(CircularBottomNavigationController navController) => this._navigationController = navController;
/// Force the [CarouselSlider] to navigate to another page. /// Force the [CarouselSlider] to navigate to another page.
void gotoPage(int page) => (this._pageController != null) ? this._pageController.jumpToPage(page) : {}; void gotoPage(int page) {
if (this._pageController != null)
this._pageController.jumpToPage(page);
}
/// Forces the [CircularBottomNavigation] to the correct position.
void navbarToPage(int page) {
if (this._navigationController != null)
this._navigationController.value = (page + 1) % 3;
}
} }
\ No newline at end of file
...@@ -9,7 +9,7 @@ import 'package:logair_application/logic/handlers/network_handler.dart'; ...@@ -9,7 +9,7 @@ import 'package:logair_application/logic/handlers/network_handler.dart';
import 'package:logair_application/logic/data_header.dart'; import 'package:logair_application/logic/data_header.dart';
import 'package:logair_application/logic/data_packet.dart'; import 'package:logair_application/logic/data_packet.dart';
import 'package:logair_application/logic/handlers/position_handler.dart'; import 'package:logair_application/logic/handlers/position_handler.dart';
import 'package:logair_application/utils/pm_symbol.dart'; import 'package:logair_application/utils/enums/pm_symbol.dart';
/// The [MapDisplayController] is a [Singleton] that handles the mapping of information. /// The [MapDisplayController] is a [Singleton] that handles the mapping of information.
class MapDisplayController { class MapDisplayController {
...@@ -85,7 +85,8 @@ class MapDisplayController { ...@@ -85,7 +85,8 @@ class MapDisplayController {
if (this._pmMarkers.length > maxPoints) if (this._pmMarkers.length > maxPoints)
this._pmMarkers.removeRange(0, this._pmMarkers.length - 200); this._pmMarkers.removeRange(0, this._pmMarkers.length - 200);
this._pmMarkers.add(_buildPMMarker(position, value)); if (value != null)
this._pmMarkers.add(_buildPMMarker(position, value));
} }
/// This function is executed on first initialization of the [MapDisplayController] /// This function is executed on first initialization of the [MapDisplayController]
......
...@@ -105,6 +105,7 @@ class DataHandler { ...@@ -105,6 +105,7 @@ class DataHandler {
} }
} }
/// This destroys the elements it depends on to avoid duplication or wrong information
void dispose() { void dispose() {
DataHeader().dispose(); DataHeader().dispose();
this._data.removeWhere((element) => true); this._data.removeWhere((element) => true);
......
...@@ -11,7 +11,7 @@ import 'package:logair_application/logic/handlers/data_handler.dart'; ...@@ -11,7 +11,7 @@ import 'package:logair_application/logic/handlers/data_handler.dart';
import 'package:logair_application/logic/handlers/database_handler.dart'; import 'package:logair_application/logic/handlers/database_handler.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
/// Singleton data structure that contains services enabling the application to send data to a webserver. /// This singleton data structure that contains services enabling the application to send data to a webserver.
class NetworkHandler { class NetworkHandler {
factory NetworkHandler() => _singleton; factory NetworkHandler() => _singleton;
...@@ -24,6 +24,7 @@ class NetworkHandler { ...@@ -24,6 +24,7 @@ class NetworkHandler {
static final NetworkHandler _singleton = new NetworkHandler._internal(); static final NetworkHandler _singleton = new NetworkHandler._internal();
DateTime _lastServerTransmission; DateTime _lastServerTransmission;
/// Method to send acquired data packets by using a POST requests. /// Method to send acquired data packets by using a POST requests.
...@@ -32,7 +33,6 @@ class NetworkHandler { ...@@ -32,7 +33,6 @@ class NetworkHandler {
String url = 'https://api.logair.unige.ch/v1/service'; String url = 'https://api.logair.unige.ch/v1/service';
/// Break conditions ([DataHeader] unset or no [DataPacket] available). /// Break conditions ([DataHeader] unset or no [DataPacket] available).
// TODO add url to db,
if (!DataHeader().headerSet || DataHandler().getData().length == 0) if (!DataHeader().headerSet || DataHandler().getData().length == 0)
return; return;
...@@ -55,13 +55,18 @@ class NetworkHandler { ...@@ -55,13 +55,18 @@ class NetworkHandler {
postData.addAll(packetList); postData.addAll(packetList);
/// Attempt to send the data to the endpoint via HTTP POST request. /// Attempt to send the data to the endpoint via HTTP POST request.
http.Response response = await http.post( http.Response response;
url, try {
headers: { "accept": "application/json", "content-type": "application/json" }, response = await http.post(
body: json.encode(postData) url,
) headers: { "accept": "application/json", "content-type": "application/json" },
body: json.encode(postData)
);
/// On error, the error should be ignored and not break the thread. /// On error, the error should be ignored and not break the thread.
.catchError((e) => print("${e.toString()} COULDN'T CONNECT")); } catch (e) {
print("${e.toString()} COULDN'T CONNECT");
response = null;
}
/// If the response is defined as an instance of [http.Response], check it's status code and remove all of the packets from the log. /// If the response is defined as an instance of [http.Response], check it's status code and remove all of the packets from the log.
if (response != null && response.statusCode == 200) { if (response != null && response.statusCode == 200) {
...@@ -79,12 +84,17 @@ class NetworkHandler { ...@@ -79,12 +84,17 @@ class NetworkHandler {
/// The default endpoint. /// The default endpoint.
String url = 'https://api.logair.unige.ch/v1/geo/bounds?device_id=$deviceId&lat1=${bounds.northEast.latitude}&lng1=${bounds.northEast.longitude}&lat2=${bounds.southWest.latitude}&lng2=${bounds.southWest.longitude}&age=${300000}&limit=${200}'; String url = 'https://api.logair.unige.ch/v1/geo/bounds?device_id=$deviceId&lat1=${bounds.northEast.latitude}&lng1=${bounds.northEast.longitude}&lat2=${bounds.southWest.latitude}&lng2=${bounds.southWest.longitude}&age=${300000}&limit=${200}';
/// Attempt to send the data to the endpoint via HTTP POST request. /// Attempt to send the data to the endpoint via HTTP POST request.
http.Response response = await http.get( http.Response response;
url, try {
headers: { "accept": "application/json", "content-type": "application/json" }, response = await http.get(
) url,
headers: { "accept": "application/json", "content-type": "application/json" },
);
/// On error, the error should be ignored and not break the thread. /// On error, the error should be ignored and not break the thread.
.catchError((e) => print('COULDN\'T CONNECT')); } catch (e) {
print("${e.toString()} COULDN'T CONNECT");
response = null;
}
if (response != null && response.statusCode == 200) { if (response != null && response.statusCode == 200) {
// TODO Complete // TODO Complete
......
import 'package:flutter/material.dart';
class CardPainter extends CustomPainter {
CardPainter({@required this.isLeft, @required this.battery, @required this.color});
final bool isLeft;
int battery;
Color color;
setColor(Color newColor) {
this.color = newColor;
}
@override
void paint(Canvas canvas, Size size) {
final shapeBounds = Rect.fromLTRB(0, 0, size.width, size.height);
_drawBackground(canvas, shapeBounds);
}
@override
bool shouldRepaint(CardPainter oldDelegate) {
return color != oldDelegate.color;
}
void _drawBackground(Canvas canvas, Rect shapeBounds) {
final Paint paint = Paint()..color = color;
final rectWidth = shapeBounds.width * this.battery / 100;
final backgroundPath = (this.isLeft) ?
(Path()
..moveTo(shapeBounds.left, shapeBounds.top)
..lineTo(shapeBounds.bottomLeft.dx, shapeBounds.bottomLeft.dy)
..lineTo(shapeBounds.bottomLeft.dx + rectWidth, shapeBounds.bottomRight.dy)
..lineTo(shapeBounds.bottomLeft.dx + rectWidth, shapeBounds.topRight.dy) //7
..close()) :
(Path()
..moveTo(shapeBounds.right, shapeBounds.top) //3
..lineTo(shapeBounds.bottomRight.dx, shapeBounds.bottomRight.dy)
..lineTo(shapeBounds.bottomRight.dx - rectWidth, shapeBounds.bottomRight.dy)
..lineTo(shapeBounds.topRight.dx - rectWidth, shapeBounds.topRight.dy) //7
..close()); //8
canvas.drawPath(backgroundPath, paint);
}
}
\ No newline at end of file
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:logair_application/logic/handlers/data_handler.dart'; import 'package:logair_application/logic/handlers/data_handler.dart';
import 'package:logair_application/ui/carousel_card.dart'; import 'package:logair_application/ui/components/common/carousel_card.dart';
import 'package:logair_application/ui/components/data_tile.dart'; import 'package:logair_application/ui/components/body/data/graph/graph.dart';
import 'package:logair_application/ui/components/graph/graph.dart'; import 'package:logair_application/ui/components/body/data/tiles/data_tile.dart';
class DataWidget extends StatelessWidget { class DataWidget extends StatelessWidget {
DataWidget(); DataWidget();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Widget widget = Center( Widget widget = Center(
child: Column( child: Column(
children: [ children: [
// Local data (Chart + Data points) // Local data (Chart + Data points)
Graph(), Graph(),
DataTile(DataHandler().getDataStream(), false, ''), DataTile(DataHandler().getDataStream(), false, ''),
// Bar (Locations + Add new -> Pop to new route) SizedBox(height: 10,),
Container( // Bar (Locations + Add new -> Pop to new route)
color: Colors.grey, Container(
child: Row( decoration: BoxDecoration(
children: [ color: Colors.grey[300],
Expanded( borderRadius: BorderRadius.only(topLeft: Radius.circular(5), topRight: Radius.circular(5))
child: Text( ),
'Other Locations', child: Row(
textAlign: TextAlign.center, children: [
), Expanded(
), child: Text(
IconButton( 'Locations of Interest',
onPressed: () => {}, textAlign: TextAlign.center,
icon: Icon(Icons.add), style: TextStyle(
) fontSize: 18
], ),
), ),
), ),
Column( IconButton(
children: [ onPressed: () => {},
DataTile(DataHandler().getMockDataStream(), true, 'Home'), icon: Icon(Icons.add),
DataTile(DataHandler().getMockDataStream(), true, 'Work'), )
DataTile(DataHandler().getMockDataStream(), true, 'C'), ],
DataTile(DataHandler().getMockDataStream(), true, 'D'), ),
DataTile(DataHandler().getMockDataStream(), true, 'E'), ),
DataTile(DataHandler().getMockDataStream(), true, 'F'), Column(
DataTile(DataHandler().getMockDataStream(), true, 'G'), children: [
DataTile(DataHandler().getMockDataStream(), true, 'H'), DataTile(DataHandler().getMockDataStream(), true, 'Home'),
DataTile(DataHandler().getMockDataStream(), true, 'I'), DataTile(DataHandler().getMockDataStream(), true, 'Work'),
], DataTile(DataHandler().getMockDataStream(), true, 'C'),
), DataTile(DataHandler().getMockDataStream(), true, 'D'),
], DataTile(DataHandler().getMockDataStream(), true, 'E'),
) DataTile(DataHandler().getMockDataStream(), true, 'F'),
); DataTile(DataHandler().getMockDataStream(), true, 'G'),
return CarouselCard(child: widget); DataTile(DataHandler().getMockDataStream(), true, 'H'),
} DataTile(DataHandler().getMockDataStream(), true, 'I'),
} SizedBox(height: 30,)
],
),
],
)
);
return CarouselCard(child: widget);
}
}
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:logair_application/ui/components/graph/graph_colors.dart'; import 'package:logair_application/ui/components/body/data/graph/graph_colors.dart';
import 'package:logair_application/ui/components/graph/graph_controller.dart'; import 'package:logair_application/ui/components/body/data/graph/graph_controller.dart';
import 'package:logair_application/ui/components/graph/indicator.dart'; import 'package:logair_application/ui/components/body/data/graph/indicator.dart';
/// WIP /// WIP
/// TODO Add axis titles /// TODO Add axis titles
/// This graph should display the average quality of the air in 5 second increments. /// This graph displays the average quality of the air in 5 second increments.
class Graph extends StatefulWidget { class Graph extends StatefulWidget {
Graph({Key key}) : super(key: key); Graph({Key key}) : super(key: key);
...@@ -16,8 +15,24 @@ class Graph extends StatefulWidget { ...@@ -16,8 +15,24 @@ class Graph extends StatefulWidget {
} }
class _GraphState extends State<Graph> { class _GraphState extends State<Graph> {
/// The first registered timestamp.
double start;
/// The current timestamp.
double now;
/// The maximum y-axis coordinate.
double yMax = 0;
List<FlSpot> spotsPM1 = [FlSpot(0, 0)];
List<FlSpot> spotsPM2_5 = [FlSpot(0, 0)];
List<FlSpot> spotsPM4 = [FlSpot(0, 0)];
List<FlSpot> spotsPM10 = [FlSpot(0, 0)];
_GraphState() { _GraphState() {
/// This gets the average PM data for the last 5 seconds and modifies the graph state with this data.
GraphController().getGraphData().listen((Map<String, dynamic> newData) { GraphController().getGraphData().listen((Map<String, dynamic> newData) {
/// Focus guard
if (this.mounted) { if (this.mounted) {
setState(() { setState(() {
start = newData['start']; start = newData['start'];
...@@ -25,25 +40,15 @@ class _GraphState extends State<Graph> { ...@@ -25,25 +40,15 @@ class _GraphState extends State<Graph> {
spotsPM2_5 = newData['spotsPM2_5']; spotsPM2_5 = newData['spotsPM2_5'];
spotsPM4 = newData['spotsPM4']; spotsPM4 = newData['spotsPM4'];
spotsPM10 = newData['spotsPM10']; spotsPM10 = newData['spotsPM10'];
max = newData['max']; yMax = newData['max'];
now = newData['now']; now = newData['now'];
}); });
} }
}); });
} }
closeTo(double value, double reference, double delta) => reference - delta <= value && value <= reference + delta; /// This creates a line of [FlSpot] of the specific [color]
_generateLine(List<FlSpot> data, Color color) => LineChartBarData(
double start;
double now;
double max = 0;
List<FlSpot> spotsPM1 = [FlSpot(0, 0)];
List<FlSpot> spotsPM2_5 = [FlSpot(0, 0)];
List<FlSpot> spotsPM4 = [FlSpot(0, 0)];
List<FlSpot> spotsPM10 = [FlSpot(0, 0)];
generateLine(List<FlSpot> data, Color color) => LineChartBarData(
spots: data, spots: data,
isCurved: false, isCurved: false,
colors: [color], colors: [color],
...@@ -63,9 +68,7 @@ class _GraphState extends State<Graph> { ...@@ -63,9 +68,7 @@ class _GraphState extends State<Graph> {
child: LineChart( child: LineChart(
LineChartData( LineChartData(
lineTouchData: LineTouchData( lineTouchData: LineTouchData(
touchCallback: (lineTouchResponse) => { touchCallback: (lineTouchResponse) => { },
print(lineTouchResponse.lineBarSpots.map((e) => e.props))
},
handleBuiltInTouches: true, handleBuiltInTouches: true,
), ),
gridData: FlGridData( gridData: FlGridData(
...@@ -73,7 +76,7 @@ class _GraphState extends State<Graph> { ...@@ -73,7 +76,7 @@ class _GraphState extends State<Graph> {
drawHorizontalLine: true, drawHorizontalLine: true,
horizontalInterval: 5, horizontalInterval: 5,
), ),
// Build from DataPacket would enable getting every 10 seconds add HH:mm:ss // Build data with timestamp.
titlesData: FlTitlesData( titlesData: FlTitlesData(
bottomTitles: SideTitles( bottomTitles: SideTitles(
showTitles: true, showTitles: true,
...@@ -93,7 +96,6 @@ class _GraphState extends State<Graph> { ...@@ -93,7 +96,6 @@ class _GraphState extends State<Graph> {
return ''; return '';
}, },
), ),
// TODO Set values for PM
leftTitles: SideTitles( leftTitles: SideTitles(
showTitles: true, showTitles: true,
interval: 10, interval: 10,
...@@ -120,21 +122,32 @@ class _GraphState extends State<Graph> { ...@@ -120,21 +122,32 @@ class _GraphState extends State<Graph> {
), ),
minX: (now ?? 0) - 130, minX: (now ?? 0) - 130,
maxX: (now ?? 0) + 10, maxX: (now ?? 0) + 10,
maxY: (this.max ?? 0) + 10, maxY: (this.yMax ?? 0) + 10,
minY: 0, minY: 0,
clipToBorder: true,
lineBarsData: [ lineBarsData: [
generateLine(spotsPM1, GraphColors.PM1.color), _generateLine(spotsPM1, GraphColors.PM1.color),
generateLine(spotsPM2_5, GraphColors.PM2_5.color), _generateLine(spotsPM2_5, GraphColors.PM2_5.color),
generateLine(spotsPM4, GraphColors.PM4.color), _generateLine(spotsPM4, GraphColors.PM4.color),
generateLine(spotsPM10, GraphColors.PM10.color), _generateLine(spotsPM10, GraphColors.PM10.color),
], ],
axisTitleData: FlAxisTitleData( axisTitleData: FlAxisTitleData(
show: true, show: true,
leftTitle: AxisTitle( leftTitle: AxisTitle(
showTitle: true,
titleText: 'PM density µg/m³', titleText: 'PM density µg/m³',
margin: 0,
textStyle: TextStyle( textStyle: TextStyle(
fontSize: 12,
color: Colors.black
)
),
bottomTitle: AxisTitle(
showTitle: true,
titleText: 'Time',
margin: 0,
textStyle: TextStyle(
fontSize: 12,
color: Colors.black
) )
) )
) )
...@@ -150,7 +163,7 @@ class _GraphState extends State<Graph> { ...@@ -150,7 +163,7 @@ class _GraphState extends State<Graph> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: GraphColors.list.map((GraphColors gc) => children: GraphColors.list.map((GraphColors gc) =>
Indicator( Indicator(
text: gc.text, text: gc.label,
color: gc.color, color: gc.color,
isSquare: true, isSquare: true,
) )
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:logair_application/ui/components/graph/graph.dart'; import 'package:logair_application/ui/components/body/data/graph/graph.dart';
/// Enumeration of representative colors for the different [Graph] lines. /// Enumeration of representative colors for the different [Graph] lines.
class GraphColors { class GraphColors {
/// Reference Key (for display)
final String _key; final String _key;
/// The color that represents the [_key]
final Color _value; final Color _value;
/// Enum constructor with a <K, V>
const GraphColors._internal(this._key, this._value); const GraphColors._internal(this._key, this._value);
/// Overriden [toString] method, this helps with debugging the values.
toString() => 'Enum.$_key ~> $_value'; toString() => 'Enum.$_key ~> $_value';
String get text => _key; /// This is a getter for the label
String get label => _key;
/// This is a getter for the color associated to the label
Color get color => _value; Color get color => _value;
/// [GraphColors] representation for PM 1
static const PM1 = const GraphColors._internal('PM 1', Color(0xff0293ee)); static const PM1 = const GraphColors._internal('PM 1', Color(0xff0293ee));
/// [GraphColors] representation for PM 2.5
static const PM2_5 = const GraphColors._internal('PM 2.5', Color(0xfff8b250)); static const PM2_5 = const GraphColors._internal('PM 2.5', Color(0xfff8b250));
/// [GraphColors] representation for PM 4
static const PM4 = const GraphColors._internal('PM 4', Color(0xff845bef)); static const PM4 = const GraphColors._internal('PM 4', Color(0xff845bef));
/// [GraphColors] representation for PM 10
static const PM10 = const GraphColors._internal('PM 10', Color(0xff13d38e)); static const PM10 = const GraphColors._internal('PM 10', Color(0xff13d38e));
/// This is a getter for the list of all [GraphColors] represented by this "enum"
static List<GraphColors> get list => [PM1, PM2_5, PM4, PM10]; static List<GraphColors> get list => [PM1, PM2_5, PM4, PM10];
} }<