Commit 351e134c authored by Administrator's avatar Administrator

overhauled activity list, fixed overflows for charts

parent e3659cc7
......@@ -11,6 +11,7 @@ import 'package:fit_parser/fit_parser.dart';
import 'package:path_provider/path_provider.dart';
import 'package:encrateia/utils/date_time_utils.dart';
import 'dart:developer';
import 'package:intl/intl.dart';
class Activity extends ChangeNotifier {
DbActivity db;
......@@ -37,19 +38,61 @@ class Activity extends ChangeNotifier {
Duration movingDuration() => Duration(seconds: db.movingTime ?? 0);
download({@required Athlete athlete}) async {
int statusCode = await StravaFitDownload.byId(
id: db.stravaId.toString(),
athlete: athlete,
);
await StravaFitDownload.byId(id: db.stravaId.toString(), athlete: athlete);
setState("downloaded");
}
setState(String state) {
db.state = state;
db.save();
db
..state = state
..save();
notifyListeners();
}
distanceString() {
if (db.totalDistance != null) {
return (db.totalDistance / 1000).toStringAsFixed(2) + " km";
} else
return "";
}
heartRateString() {
if (db.avgHeartRate != null) {
return db.avgHeartRate.toString() + " bpm";
} else
return "";
}
timeString() {
if (db.avgHeartRate != null) {
return DateFormat("H:mm")
.format(db.timeCreated);
} else
return "";
}
dateString() {
if (db.avgHeartRate != null) {
return DateFormat("d MMM yy")
.format(db.timeCreated);
} else
return "";
}
paceString() {
if (db.avgHeartRate != null) {
return db.avgSpeed.toPace() + "/km";
} else
return "";
}
Future<String> get averagePower async{
List<Event> records = await Event.recordsByActivity(activity: this);
String averagePower = Lap.averagePower(records: records);
notifyListeners();
return averagePower;
}
parse({@required Athlete athlete}) async {
var appDocDir = await getApplicationDocumentsDirectory();
var fitFile = FitFile(path: appDocDir.path + '/${db.stravaId}.fit').parse();
......@@ -196,7 +239,7 @@ class Activity extends ChangeNotifier {
print("Persisted activity ${db.stravaId} to database.");
}
delete() async{
delete() async {
await this.db.delete();
}
......
......@@ -104,7 +104,10 @@ class Lap {
static String averagePower({List<Event> records}) {
var powers = records.map((record) => record.db.power).nonZero();
return powers.mean().toStringAsFixed(1);
if (powers.length > 0) {
return powers.mean().toStringAsFixed(1) + " W";
} else
return "";
}
static String sdevPower({List<Event> records}) {
......
......@@ -23,8 +23,8 @@ class _ListActivitiesScreenState extends State<ListActivitiesScreen> {
@override
initState() {
getActivities();
super.initState();
getActivities();
}
@override
......@@ -39,45 +39,52 @@ class _ListActivitiesScreenState extends State<ListActivitiesScreen> {
if (widget.athlete.email != null && widget.athlete.password != null)
ListTile(
leading: Icon(Icons.cloud_download),
title: Text(
"Download Activities from Strava",
),
title: Text("Download Activities from Strava"),
onTap: () => queryStrava()),
if (widget.athlete.password == null)
ListTile(
leading: Icon(
Icons.error,
color: Colors.red,
),
leading: Icon(Icons.error, color: Colors.red),
title: Text(
"Strava password not provided yet!",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
style:
TextStyle(fontWeight: FontWeight.bold, color: Colors.red),
),
),
if (widget.athlete.email == null)
ListTile(
leading: Icon(
Icons.error,
color: Colors.red,
),
leading: Icon(Icons.error, color: Colors.red),
title: Text(
"Strava email not provided yet!",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
style:
TextStyle(fontWeight: FontWeight.bold, color: Colors.red),
),
),
if (activities != null)
for (Activity activity in activities)
ListTile(
leading: Icon(Icons.directions_run),
title: Text("${activity.db.type} "
"${activity.db.stravaId}"),
subtitle: Text(activity.db.name ?? "Activity"),
title: Text(activity.db.name ?? "Activity"),
subtitle: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(activity.dateString() +
"\n" +
activity.distanceString()),
Text(activity.timeString() + "\n" + activity.paceString()),
FutureBuilder<String>(
future: activity.averagePower,
builder: (BuildContext context,
AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return Text(activity.heartRateString() +
"\n" +
snapshot.data);
} else {
return Text(activity.heartRateString() + "\n ...");
}
}),
],
),
trailing: ChangeNotifierProvider.value(
value: activity,
child: Consumer<Activity>(
......@@ -113,7 +120,6 @@ class _ListActivitiesScreenState extends State<ListActivitiesScreen> {
Future getActivities() async {
activities = await Activity.all();
print(activities.length);
setState(() {});
}
......
......@@ -81,8 +81,9 @@ class ActivityHeartRateChart extends StatelessWidget {
),
);
} else {
return Center(
child: Text("Loading"),
return Container(
height: 100,
child: Center(child: Text("Loading")),
);
}
},
......
......@@ -21,46 +21,39 @@ class ActivityHeartRateWidget extends StatelessWidget {
snapshot.data.map((value) => value.db.heartRate).nonZero();
if (heartRates.length > 0) {
var records = snapshot.data;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
ActivityHeartRateChart(records: records, activity: activity),
Expanded(
child: ListTileTheme(
iconColor: Colors.deepOrange,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
ListTile(
leading: Icon(Icons.pets),
title: Text(Lap.averageHeartRate(records: records)),
subtitle: Text("average heart rate"),
),
ListTile(
leading: Icon(Icons.expand_more),
title: Text(Lap.minHeartRate(records: records)),
subtitle: Text("minimum heart rate"),
),
ListTile(
leading: Icon(Icons.expand_less),
title: Text(Lap.maxHeartRate(records: records)),
subtitle: Text("maximum heart rate"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(Lap.sdevHeartRate(records: records)),
subtitle: Text("standard deviation heart rate"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
return ListTileTheme(
iconColor: Colors.deepOrange,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
ActivityHeartRateChart(records: records, activity: activity),
ListTile(
leading: Icon(Icons.pets),
title: Text(Lap.averageHeartRate(records: records)),
subtitle: Text("average heart rate"),
),
),
],
ListTile(
leading: Icon(Icons.expand_more),
title: Text(Lap.minHeartRate(records: records)),
subtitle: Text("minimum heart rate"),
),
ListTile(
leading: Icon(Icons.expand_less),
title: Text(Lap.maxHeartRate(records: records)),
subtitle: Text("maximum heart rate"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(Lap.sdevHeartRate(records: records)),
subtitle: Text("standard deviation heart rate"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
);
} else {
return Center(
......
......@@ -80,9 +80,11 @@ class ActivityPowerChart extends StatelessWidget {
),
);
} else {
return Center(
child: Text("Loading"),
return Container(
height: 100,
child: Center(child: Text("Loading")),
);
}
},
);
......
......@@ -18,11 +18,8 @@ class ActivityPowerDurationWidget extends StatelessWidget {
var powerValues =
snapshot.data.map((value) => value.db.power).nonZero();
if (powerValues.length > 0) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
PowerDurationChart(records: snapshot.data),
],
return SingleChildScrollView(
child: PowerDurationChart(records: snapshot.data),
);
} else {
return Center(
......@@ -30,8 +27,9 @@ class ActivityPowerDurationWidget extends StatelessWidget {
);
}
} else {
return Center(
child: Text("Loading"),
return Container(
height: 100,
child: Center(child: Text("Loading")),
);
}
},
......
......@@ -20,50 +20,40 @@ class ActivityPowerWidget extends StatelessWidget {
snapshot.data.map((value) => value.db.power).nonZero();
if (powerValues.length > 0) {
var records = snapshot.data;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
ActivityPowerChart(
records: records,
activity: activity,
),
Expanded(
child: ListTileTheme(
iconColor: Colors.deepOrange,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
ListTile(
leading: Icon(Icons.ev_station),
title:
Text(Lap.averagePower(records: records) + " W"),
subtitle: Text("average power"),
),
ListTile(
leading: Icon(Icons.expand_more),
title: Text(Lap.minPower(records: records) + " W"),
subtitle: Text("minimum power"),
),
ListTile(
leading: Icon(Icons.expand_less),
title: Text(Lap.maxPower(records: records) + " W"),
subtitle: Text("maximum power"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(Lap.sdevPower(records: records) + " W"),
subtitle: Text("standard deviation power"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
return ListTileTheme(
iconColor: Colors.deepOrange,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
ActivityPowerChart(records: records, activity: activity),
ListTile(
leading: Icon(Icons.ev_station),
title:
Text(Lap.averagePower(records: records) + " W"),
subtitle: Text("average power"),
),
),
],
ListTile(
leading: Icon(Icons.expand_more),
title: Text(Lap.minPower(records: records) + " W"),
subtitle: Text("minimum power"),
),
ListTile(
leading: Icon(Icons.expand_less),
title: Text(Lap.maxPower(records: records) + " W"),
subtitle: Text("maximum power"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(Lap.sdevPower(records: records) + " W"),
subtitle: Text("standard deviation power"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
);
} else {
return Center(
......
......@@ -19,46 +19,39 @@ class LapHeartRateWidget extends StatelessWidget {
snapshot.data.map((value) => value.db.heartRate).nonZero();
if (heartRates.length > 0) {
var records = snapshot.data;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
LapHeartRateChart(records: records),
Expanded(
child: ListTileTheme(
iconColor: Colors.lightGreen,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
ListTile(
leading: Icon(Icons.pets),
title: Text(Lap.averageHeartRate(records: records)),
subtitle: Text("average heart rate"),
),
ListTile(
leading: Icon(Icons.expand_more),
title: Text(Lap.minHeartRate(records: records)),
subtitle: Text("minimum heart rate"),
),
ListTile(
leading: Icon(Icons.expand_less),
title: Text(Lap.maxHeartRate(records: records)),
subtitle: Text("maximum heart rate"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(Lap.sdevHeartRate(records: records)),
subtitle: Text("standard deviation heart rate"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
return ListTileTheme(
iconColor: Colors.lightGreen,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
LapHeartRateChart(records: records),
ListTile(
leading: Icon(Icons.pets),
title: Text(Lap.averageHeartRate(records: records)),
subtitle: Text("average heart rate"),
),
),
],
ListTile(
leading: Icon(Icons.expand_more),
title: Text(Lap.minHeartRate(records: records)),
subtitle: Text("minimum heart rate"),
),
ListTile(
leading: Icon(Icons.expand_less),
title: Text(Lap.maxHeartRate(records: records)),
subtitle: Text("maximum heart rate"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(Lap.sdevHeartRate(records: records)),
subtitle: Text("standard deviation heart rate"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
);
} else {
return Center(
......
......@@ -18,11 +18,8 @@ class LapPowerDurationWidget extends StatelessWidget {
var powerValues =
snapshot.data.map((value) => value.db.power).nonZero();
if (powerValues.length > 0) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
PowerDurationChart(records: snapshot.data),
],
return SingleChildScrollView(
child: PowerDurationChart(records: snapshot.data, ),
);
} else {
return Center(
......
......@@ -19,47 +19,39 @@ class LapPowerWidget extends StatelessWidget {
snapshot.data.map((value) => value.db.power).nonZero();
if (powerValues.length > 0) {
var records = snapshot.data;
return Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
LapPowerChart(records: records),
Expanded(
child: ListTileTheme(
iconColor: Colors.lightGreen,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
ListTile(
leading: Icon(Icons.ev_station),
title:
Text(Lap.averagePower(records: records) + " W"),
subtitle: Text("average power"),
),
ListTile(
leading: Icon(Icons.expand_more),
title: Text(Lap.minPower(records: records) + " W"),
subtitle: Text("minimum power"),
),
ListTile(
leading: Icon(Icons.expand_less),
title: Text(Lap.maxPower(records: records) + " W"),
subtitle: Text("maximum power"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(Lap.sdevPower(records: records) + " W"),
subtitle: Text("standard deviation power"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
return ListTileTheme(
iconColor: Colors.lightGreen,
child: ListView(
padding: EdgeInsets.only(left: 25),
children: <Widget>[
LapPowerChart(records: records),
ListTile(
leading: Icon(Icons.ev_station),
title: Text(Lap.averagePower(records: records) + " W"),
subtitle: Text("average power"),
),
),
],
ListTile(
leading: Icon(Icons.expand_more),
title: Text(Lap.minPower(records: records) + " W"),
subtitle: Text("minimum power"),
),
ListTile(
leading: Icon(Icons.expand_less),
title: Text(Lap.maxPower(records: records) + " W"),
subtitle: Text("maximum power"),
),
ListTile(
leading: Icon(Icons.unfold_more),
title: Text(Lap.sdevPower(records: records) + " W"),
subtitle: Text("standard deviation power"),
),
ListTile(
leading: Icon(Icons.playlist_add),
title: Text(records.length.toString()),
subtitle: Text("number of measurements"),
),
],
),
);
} else {
return Center(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment