Optimize Loading times
This commit is contained in:
182
lib/Analytics.dart
Normal file
182
lib/Analytics.dart
Normal file
@@ -0,0 +1,182 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:tasktracker/AvgDay.dart';
|
||||
import 'package:tasktracker/main.dart';
|
||||
|
||||
import 'Data.dart';
|
||||
import 'DebugHelper.dart';
|
||||
import 'User.dart' as User;
|
||||
|
||||
class AnalyticsPage extends StatefulWidget {
|
||||
const AnalyticsPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AnalyticsPage> createState() => _AnalyticsPageState();
|
||||
}
|
||||
|
||||
class _AnalyticsPageState extends State<AnalyticsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
// for (var value in avgActs) {
|
||||
// Debug.LogResponse('${value.taskType.name} : ${DateFormat('HH:mm').format(value.startTime)} - ${DateFormat('HH:mm').format(value.endTime)}');
|
||||
// }
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Row(
|
||||
children: [FaIcon(FontAwesomeIcons.chartLine),SizedBox(width: 15,), Text("Analytics")],
|
||||
)),
|
||||
drawer: navDrawer(context, 1),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
child:Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Average Day',style: TextStyle(fontSize: 17)),
|
||||
MaterialButton(
|
||||
|
||||
color: Colors.green,
|
||||
onPressed: (){
|
||||
Navigator.of(context).push(MaterialPageRoute(builder: (context)=> AvgDayPage()));
|
||||
},
|
||||
child: Text('More...'),
|
||||
)
|
||||
],
|
||||
),
|
||||
Divider(),
|
||||
|
||||
|
||||
],
|
||||
),
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AnalyticTools{
|
||||
|
||||
static double dailyThreshold = 0.9;
|
||||
static int activityGroupingThreshold = 4;
|
||||
|
||||
|
||||
static List<Activity> getAverageDayActs(DateTimeRange range){
|
||||
int totalDays = range.end.difference(range.start).inDays;
|
||||
|
||||
Map<TaskType, List<AvgActData>> avgActs = <TaskType, List<AvgActData>>{};
|
||||
Map<TaskType, List<DateTimeRange>> acts = <TaskType, List<DateTimeRange>>{};
|
||||
List<Activity> listToReturn = [];
|
||||
//PASS 1: Split Activities and mark their time range
|
||||
User.activities.forEach((element) {
|
||||
if(element.startTime.isAfter(range.start) && element.endTime.isBefore(range.end)){
|
||||
//Eligible activity to calculate
|
||||
if(acts.containsKey(element.taskType)){
|
||||
acts[element.taskType]!.add(DateTimeRange(start: element.startTime, end: element.endTime));
|
||||
}else{
|
||||
acts.putIfAbsent(element.taskType, () => [DateTimeRange(start: element.startTime, end: element.endTime)]);
|
||||
}
|
||||
}
|
||||
});
|
||||
Debug.Log('Analysing ${acts.length} activities');
|
||||
//PASS 2: Calculate avg Time Range for each Activity
|
||||
acts.forEach((key, value) {
|
||||
if(value.length < totalDays * dailyThreshold){
|
||||
//Not a frequent Activity,
|
||||
}else{
|
||||
//Iterate through the time ranges of this activity
|
||||
for (var _actTime in value) {
|
||||
DateTime _start = DateTime(0,0,0,_actTime.start.hour, _actTime.start.minute);
|
||||
DateTime _end = DateTime(0,0,0,_actTime.end.hour, _actTime.end.minute);
|
||||
if(_start.isAfter(_end)){Debug.LogError('${key.name} start after end? : $_start, $_end'); continue;}
|
||||
DateTimeRange actTime = DateTimeRange(start: _start, end: _end);
|
||||
if(!avgActs.containsKey(key)){
|
||||
avgActs.putIfAbsent(key, () => []);
|
||||
}
|
||||
if(avgActs[key]!.isEmpty){
|
||||
//No need to check groups. No groups exists.
|
||||
avgActs[key]!.add(AvgActData(actTime, 1, 1));
|
||||
}else{
|
||||
//Check for the closest time group
|
||||
bool foundGroup = false;
|
||||
for(int i = 0; i < avgActs[key]!.length; i++){
|
||||
if(foundGroup){continue;}
|
||||
DateTimeRange avgTime = avgActs[key]![i].avgRange;
|
||||
int count = avgActs[key]![i].count;
|
||||
if(actTime.start.difference(avgTime.start).inHours.abs() < activityGroupingThreshold && actTime.end.difference(avgTime.end).inHours.abs() < activityGroupingThreshold){
|
||||
foundGroup = true;
|
||||
int curStartMin = (avgTime.start.hour * 60) + avgTime.start.minute;
|
||||
int curEndMin = (avgTime.end.hour * 60) + avgTime.end.minute;
|
||||
int newStartMin = (actTime.start.hour * 60) + actTime.start.minute;
|
||||
int newEndMin = (actTime.end.hour * 60) + actTime.end.minute;
|
||||
|
||||
int avgStartMin = ((curStartMin + newStartMin)/2).toInt();
|
||||
int avgEndMin = ((curEndMin + newEndMin)/2).toInt();
|
||||
|
||||
Debug.Log('Avged : ${key.name} [$i] : ${avgStartMin} - ${avgEndMin}');
|
||||
if(avgStartMin > avgEndMin){
|
||||
//Malfunctioned
|
||||
Debug.LogError('Start is after End? Wut???\nAvged : ${key.name}[$i] : ${avgStartMin} - ${avgEndMin}');
|
||||
}else {
|
||||
DateTime baseline = DateTime(0, 0, 0, 0, 0);
|
||||
// avgActs[key]!.keys.toList()[i] =
|
||||
// DateTimeRange(start: baseline.add(Duration(minutes: avgStartMin)), end: baseline.add(Duration(minutes: avgEndMin)));
|
||||
// avgActs[key]!.values.toList()[i]++;
|
||||
//avgActs[key]!.removeWhere((key, value) => key==avgTime);
|
||||
avgActs[key]![i].avgRange = DateTimeRange(start: baseline.add(Duration(minutes: avgStartMin)), end: baseline.add(Duration(minutes: avgEndMin)));
|
||||
avgActs[key]![i].count++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!foundGroup){
|
||||
avgActs[key]!.add(AvgActData(actTime, 1, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//PASS 3: Prepare the Activity list to return
|
||||
|
||||
avgActs.forEach((key, value) {
|
||||
value.sort((a,b) => b.count.compareTo(a.count));
|
||||
value.forEach((element) {
|
||||
Activity thisAct = Activity(key, element.avgRange.start, element.avgRange.end);
|
||||
Debug.LogResponse(
|
||||
'${thisAct.taskType.name} (${element.count}) -> (${element.dailyCountAvg}) : ${DateFormat('HH:mm').format(thisAct.startTime)} - ${DateFormat('HH:mm').format(
|
||||
thisAct.endTime)}');
|
||||
if(element.count < totalDays * dailyThreshold/2){
|
||||
Debug.Log('Ignoring due to DailyThreshold, ${element.count} < ${totalDays * dailyThreshold/2}');
|
||||
}else {
|
||||
|
||||
listToReturn.add(thisAct);
|
||||
}
|
||||
});
|
||||
// value.forEach((act, count) {
|
||||
//
|
||||
// });
|
||||
});
|
||||
|
||||
return listToReturn;
|
||||
}
|
||||
}
|
||||
|
||||
class AvgActData{
|
||||
AvgActData(this.avgRange, this.count, this.dailyCountAvg);
|
||||
|
||||
DateTimeRange avgRange;
|
||||
int count;
|
||||
double dailyCountAvg;
|
||||
}
|
||||
127
lib/AvgDay.dart
Normal file
127
lib/AvgDay.dart
Normal file
@@ -0,0 +1,127 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
import 'package:tasktracker/main.dart';
|
||||
|
||||
import 'Analytics.dart';
|
||||
import 'Data.dart';
|
||||
import 'User.dart' as User;
|
||||
class AvgDayPage extends StatefulWidget {
|
||||
const AvgDayPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<AvgDayPage> createState() => _AvgDayPageState();
|
||||
}
|
||||
|
||||
class _AvgDayPageState extends State<AvgDayPage> {
|
||||
DateFormat dFormat = DateFormat('HH:mm');
|
||||
DateTimeRange dateRange = DateTimeRange(start: DateTime.now().subtract(Duration(days: 7)), end: DateTime.now());
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Activity> avgActs = AnalyticTools.getAverageDayActs(dateRange);
|
||||
|
||||
avgActs.sort((a,b)=> a.startTime.compareTo(b.startTime));
|
||||
|
||||
return Scaffold(
|
||||
appBar:AppBar(title:Row(children: [
|
||||
FaIcon(FontAwesomeIcons.calendarDay),
|
||||
SizedBox(width: 15,),
|
||||
Text('Average Day')
|
||||
],)),
|
||||
body: Container(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
children: [
|
||||
FaIcon(FontAwesomeIcons.calendarDays),
|
||||
SizedBox(width: 10,),
|
||||
Text('Date Range',style:TextStyle(fontSize: 16)),
|
||||
SizedBox(width: 20,),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
DateTimeRange? value = await showDateRangePicker(context: context, firstDate: User.activities[User.activities.length-1].startTime , lastDate: User.activities[0].startTime);
|
||||
if (value != null) {
|
||||
dateRange = value;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
|
||||
});
|
||||
},
|
||||
child: Text((dateRange != null) ? (DateFormat("MM/dd").format(dateRange!.start) + " - " + DateFormat("MM/dd").format(dateRange!.end)) : 'n/a',
|
||||
style: TextStyle(fontSize: 18,fontWeight: FontWeight.bold)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
ScrollablePositionedList.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: avgActs.length,
|
||||
itemBuilder: (context, i){
|
||||
return Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(10, 0, 5, 0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// Text(dateFormat.format(activity.endTime)),
|
||||
|
||||
Text(dFormat.format(avgActs[i].startTime),style: TextStyle(fontSize: 16)),
|
||||
SizedBox(width: 1, height: 50, child: Container(color: Colors.grey)),
|
||||
],
|
||||
)),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
elevation: 30,
|
||||
shadowColor:HexColor.fromHex(avgActs[i].taskType!.cat!.color) ,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(avgActs[i].taskType.name,style: TextStyle(fontSize: 18)),
|
||||
Text(MinutesToTimeString(avgActs[i].endTime.difference(avgActs[i].startTime).inMinutes),style: TextStyle(fontSize: 18)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('${dFormat.format(avgActs[i].startTime)} - ${dFormat.format(avgActs[i].endTime)}'),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 2),
|
||||
decoration:
|
||||
BoxDecoration(borderRadius: BorderRadius.circular(10), color: (avgActs[i].taskType.cat!.productive) ? Colors.green : Colors.red),
|
||||
child: Text(avgActs[i].taskType.cat?.name ?? 'n/a'))
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
SizedBox(width: 1000,height: 2,child: Container(color: HexColor.fromHex(avgActs[i].taskType!.cat!.color)),),
|
||||
SizedBox(height: 10,),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'dart:developer';
|
||||
|
||||
class Debug{
|
||||
static bool enableLogging = true;
|
||||
static bool enableResponseLogging = false;
|
||||
static bool enableResponseLogging = true;
|
||||
static bool enableErrorLoggin = true;
|
||||
static bool enableTestLogging = true;
|
||||
|
||||
|
||||
240
lib/User.dart
240
lib/User.dart
@@ -64,8 +64,15 @@ Future<void> initUserData() async {
|
||||
if (cacheEnabled) {
|
||||
await initCacheDatabase();
|
||||
}
|
||||
int catCount = Sqflite.firstIntValue(await cacheDb.rawQuery('SELECT COUNT(*) FROM Categories')) ?? 0;
|
||||
int taskCount = Sqflite.firstIntValue(await cacheDb.rawQuery('SELECT COUNT(*) FROM TaskTypes')) ?? 0;
|
||||
if(catCount > 0 && taskCount > 0){
|
||||
await refreshUserData(forceOffline: true);
|
||||
refreshUserData();
|
||||
}else{
|
||||
await refreshUserData();
|
||||
}
|
||||
|
||||
await refreshUserData();
|
||||
BuildBridgeToServer();
|
||||
Debug.Log('Initializing UserData...');
|
||||
|
||||
@@ -143,19 +150,61 @@ Future<void> refreshUserData({bool forceOffline = false}) async {
|
||||
|
||||
refreshStream.add(false);
|
||||
} else {
|
||||
Debug.LogTest('updating cats ${DateTime.now()}');
|
||||
categories = await GetCategories(false);
|
||||
Debug.LogTest('updating projs ${DateTime.now()}');
|
||||
projects = await GetProjects(false);
|
||||
Debug.LogTest('updating tasks ${DateTime.now()}');
|
||||
taskTypes = await GetTaskTypes(false);
|
||||
Debug.LogTest('updating acts ${DateTime.now()}');
|
||||
activities = await GetActivities(false);
|
||||
Debug.LogTest('updating journals ${DateTime.now()}');
|
||||
journal = await GetJournals(false);
|
||||
Debug.LogTest('updating todos ${DateTime.now()}');
|
||||
todos= await GetTodos(false);
|
||||
Debug.LogTest('done refreshing ${DateTime.now()}');
|
||||
if(false) {
|
||||
Debug.LogTest('updating cats ${DateTime.now()}');
|
||||
categories = await GetCategories(false);
|
||||
Debug.LogTest('updating projs ${DateTime.now()}');
|
||||
projects = await GetProjects(false);
|
||||
Debug.LogTest('updating tasks ${DateTime.now()}');
|
||||
taskTypes = await GetTaskTypes(false);
|
||||
Debug.LogTest('updating acts ${DateTime.now()}');
|
||||
activities = await GetActivities(false);
|
||||
Debug.LogTest('updating journals ${DateTime.now()}');
|
||||
journal = await GetJournals(false);
|
||||
Debug.LogTest('updating todos ${DateTime.now()}');
|
||||
todos = await GetTodos(false);
|
||||
Debug.LogTest('done refreshing ${DateTime.now()}');
|
||||
}else {
|
||||
Debug.LogTest('Doing super update ${DateTime.now()}');
|
||||
refreshStream.add(true);
|
||||
try {
|
||||
Debug.LogTest('Requesting all data @ ${DateTime.now()}');
|
||||
http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/grab_all_data.php'),
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
List<String> data = response.body.split('<tr>');
|
||||
Debug.LogTest('Got response for all data [${response.contentLength}bytes] @ ${DateTime.now()}');
|
||||
Debug.LogTest('super update items : ${data.length}\nfilling tables\nActivities : ${data[0].length}\nProjects: ${data[1].length}');
|
||||
Debug.LogResponse(response.body);
|
||||
Debug.LogResponse(data[0],src: 'Activity');
|
||||
Debug.LogResponse(data[1],src: 'Categories');
|
||||
Debug.LogResponse(data[2],src: 'Projects');
|
||||
Debug.LogResponse(data[3],src: 'Journals');
|
||||
Debug.LogResponse(data[4],src: 'TaskTypes');
|
||||
Debug.LogResponse(data[5],src: 'Todo');
|
||||
|
||||
await fillActivityTable(data[0]);
|
||||
await fillCatsTable(data[1]);
|
||||
await fillJournalsTable(data[2]);
|
||||
await fillProjectsTable(data[3]);
|
||||
await fillTaskTypes(data[4]);
|
||||
await fillTodosTable(data[5]);
|
||||
|
||||
Debug.LogTest('Done filling @ ${DateTime.now()}');
|
||||
|
||||
categories = await GetCategories(true);
|
||||
projects = await GetProjects(true);
|
||||
taskTypes = await GetTaskTypes(true);
|
||||
activities = await GetActivities(true);
|
||||
journal = await GetJournals(true);
|
||||
todos = await GetTodos(true);
|
||||
|
||||
|
||||
} catch (e) {
|
||||
Debug.LogError("Error while Super Update $e");
|
||||
}
|
||||
refreshStream.add(false);
|
||||
Debug.LogTest('Done super update ${DateTime.now()}');
|
||||
}
|
||||
}
|
||||
|
||||
m_refreshing = false;
|
||||
@@ -343,20 +392,24 @@ Future<void> UpdateCategoriesFromServer() async {
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
|
||||
Debug.LogResponse(response.body);
|
||||
List<String> data = response.body.split("<td>");
|
||||
await cacheDb.delete("Categories");
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(catData);
|
||||
await cacheDb
|
||||
.rawInsert("INSERT OR REPLACE INTO Categories (${Category.colCatId},${Category.colName},${Category.colProductive},${Category.colColor}) "
|
||||
"VALUES ('${cat['category_id']}','${cat['name']}',${cat['productive']},'${cat['color']}') ");
|
||||
}
|
||||
await fillCatsTable(response.body);
|
||||
} catch (e) {
|
||||
Debug.LogError("Error while cats $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fillCatsTable(String response) async {
|
||||
List<String> data = response.split("<td>");
|
||||
await cacheDb.delete("Categories");
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(catData);
|
||||
await cacheDb
|
||||
.rawInsert("INSERT OR REPLACE INTO Categories (${Category.colCatId},${Category.colName},${Category.colProductive},${Category.colColor}) "
|
||||
"VALUES ('${cat['category_id']}','${cat['name']}',${cat['productive']},'${cat['color']}') ");
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<TaskType>> GetTaskTypes(bool forceOffline) async {
|
||||
if (cacheEnabled) {
|
||||
List<TaskType> _taskTypes = [];
|
||||
@@ -443,22 +496,26 @@ Future<void> UpdateTaskTypesFromServer() async {
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
|
||||
Debug.LogResponse(response.body);
|
||||
List<String> data = response.body.split("<td>");
|
||||
await cacheDb.delete("TaskTypes");
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(cat);
|
||||
await cacheDb
|
||||
.rawInsert("INSERT OR REPLACE INTO TaskTypes (${TaskType.colId},${TaskType.colName},${TaskType.colCategory},${TaskType.colRelatedProject}) "
|
||||
"VALUES ('${cat['task_id']}','${cat['name']}','${cat['category_id']}', '${cat['related_project']}') ");
|
||||
|
||||
Debug.LogResponse(await cacheDb.query("TaskTypes"));
|
||||
}
|
||||
await fillTaskTypes(response.body);
|
||||
} catch (e) {
|
||||
Debug.LogError("Error while tasks $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fillTaskTypes(String response) async {
|
||||
List<String> data = response.split("<td>");
|
||||
await cacheDb.delete("TaskTypes");
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(cat);
|
||||
await cacheDb
|
||||
.rawInsert("INSERT OR REPLACE INTO TaskTypes (${TaskType.colId},${TaskType.colName},${TaskType.colCategory},${TaskType.colRelatedProject}) "
|
||||
"VALUES ('${cat['task_id']}','${cat['name']}','${cat['category_id']}', '${cat['related_project']}') ");
|
||||
|
||||
Debug.LogResponse(await cacheDb.query("TaskTypes"));
|
||||
}
|
||||
}
|
||||
|
||||
void StartActivityTimer(String taskType, String metadata, DateTime startTime) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
@@ -618,28 +675,33 @@ Future<void> UpdateActivitiesFromServer() async {
|
||||
http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_activities.php'),
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
|
||||
await cacheDb.rawDelete("DELETE FROM Activities");
|
||||
Debug.Log('Truncate Activity Table before');
|
||||
await fillActivityTable(response.body);
|
||||
|
||||
// Debug.Log("Activity response: ${response.body}");
|
||||
if (response.body.contains("{")) {
|
||||
List<String> data = response.body.split("<td>");
|
||||
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(cat);
|
||||
await cacheDb.rawInsert(
|
||||
"INSERT OR REPLACE INTO Activities (${Activity.colType}, ${Activity.colStartTime}, ${Activity.colEndTime}, ${Activity.colMetadata}) "
|
||||
"VALUES ('${cat['task_id']}', '${cat['sTime']}','${cat['eTime']}', '${cat['metadata'].toString().replaceAll("'", "''")}') ");
|
||||
}
|
||||
} else {
|
||||
Debug.Log("No activities for now");
|
||||
}
|
||||
} catch (e) {
|
||||
Debug.Log("Error while acts $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fillActivityTable(String response) async{
|
||||
if (response.contains("{")) {
|
||||
await cacheDb.rawDelete("DELETE FROM Activities");
|
||||
Debug.Log('Truncate Activity Table before');
|
||||
List<String> data = response.split("<td>");
|
||||
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(cat);
|
||||
await cacheDb.rawInsert(
|
||||
"INSERT OR REPLACE INTO Activities (${Activity.colType}, ${Activity.colStartTime}, ${Activity.colEndTime}, ${Activity.colMetadata}) "
|
||||
"VALUES ('${cat['task_id']}', '${cat['sTime']}','${cat['eTime']}', '${cat['metadata'].toString().replaceAll("'", "''")}') ");
|
||||
}
|
||||
} else {
|
||||
Debug.Log("No activities for now");
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Project>> GetProjects(bool forceOffline) async {
|
||||
if (cacheEnabled) {
|
||||
List<Project> _projects = [];
|
||||
@@ -740,28 +802,32 @@ Future<void> UpdateProjectsFromServer() async {
|
||||
http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_projects.php'),
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
|
||||
await cacheDb.rawDelete("DELETE FROM Projects");
|
||||
Debug.Log('Truncate Projects Table before');
|
||||
|
||||
Debug.LogResponse("Projects response: ${response.body}");
|
||||
if (response.body.contains("{")) {
|
||||
List<String> data = response.body.split("<td>");
|
||||
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
Debug.LogResponse(cat, src: 'project data');
|
||||
await cacheDb.rawInsert(
|
||||
"INSERT OR REPLACE INTO Projects (${Project.colName}, ${Project.colCat}, ${Project.colSteps}, ${Project.colDeadline}, ${Project.colEta}) "
|
||||
"VALUES ('${cat['name']}', '${cat['category']}', '${cat['steps']}', '${cat['deadline']}', ${cat['eta']})");
|
||||
}
|
||||
} else {
|
||||
Debug.Log("No activities for now");
|
||||
}
|
||||
await fillProjectsTable(response.body);
|
||||
} catch (e) {
|
||||
Debug.LogError("Error while acts $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fillProjectsTable(String response) async {
|
||||
await cacheDb.rawDelete("DELETE FROM Projects");
|
||||
Debug.Log('Truncate Projects Table before');
|
||||
|
||||
Debug.LogResponse("Projects response: ${response}");
|
||||
if (response.contains("{")) {
|
||||
List<String> data = response.split("<td>");
|
||||
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
Debug.LogResponse(cat, src: 'project data');
|
||||
await cacheDb.rawInsert(
|
||||
"INSERT OR REPLACE INTO Projects (${Project.colName}, ${Project.colCat}, ${Project.colSteps}, ${Project.colDeadline}, ${Project.colEta}) "
|
||||
"VALUES ('${cat['name']}', '${cat['category']}', '${cat['steps']}', '${cat['deadline']}', ${cat['eta']})");
|
||||
}
|
||||
} else {
|
||||
Debug.Log("No projects for now");
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Journal>> GetJournals(bool forceOffline) async {
|
||||
if (cacheEnabled) {
|
||||
List<Journal> _journals = [];
|
||||
@@ -834,20 +900,27 @@ Future<void> UpdateJournalsFromServer() async {
|
||||
http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_journals.php'),
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
|
||||
Debug.LogResponse(response.body,src:'Journal');
|
||||
List<String> data = response.body.split("<td>");
|
||||
await cacheDb.delete("Journal");
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(catData);
|
||||
await cacheDb.rawInsert("INSERT OR REPLACE INTO Journal (id, ${Journal.colTitle},${Journal.colDescription}) "
|
||||
"VALUES ('${cat['id']}','${cat['title'].toString().replaceAll("'", "''")}','${cat['description'].toString().replaceAll("'", "''")}') ");
|
||||
}
|
||||
await fillJournalsTable(response.body);
|
||||
} catch (e) {
|
||||
Debug.LogError("Error while cats $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fillJournalsTable(String response) async {
|
||||
Debug.LogResponse(response,src:'Journal');
|
||||
if(response.isEmpty){
|
||||
Debug.Log('Empty Journal');
|
||||
}else{
|
||||
List<String> data = response.split("<td>");
|
||||
await cacheDb.delete("Journal");
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(catData);
|
||||
await cacheDb.rawInsert("INSERT OR REPLACE INTO Journal (id, ${Journal.colTitle},${Journal.colDescription}) "
|
||||
"VALUES ('${cat['id']}','${cat['title'].toString().replaceAll("'", "''")}','${cat['description'].toString().replaceAll("'", "''")}') ");
|
||||
}}
|
||||
}
|
||||
|
||||
Future<List<Todo>> GetTodos(bool forceOffline) async {
|
||||
if (cacheEnabled) {
|
||||
List<Todo> _todos = [];
|
||||
@@ -927,16 +1000,27 @@ Future<void> UpdateTodosFromServer() async {
|
||||
body: <String, String>{"username": username, "device_id": await Settings.UUID()}));
|
||||
|
||||
Debug.LogResponse(response.body);
|
||||
List<String> data = response.body.split("<td>");
|
||||
|
||||
await fillTodosTable(response.body);
|
||||
} catch (e) {
|
||||
Debug.LogError("Error while cats $e");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fillTodosTable(String response) async {
|
||||
|
||||
if (response.contains("{")) {
|
||||
List<String> data = response.split("<td>");
|
||||
await cacheDb.delete("Todos");
|
||||
for (var value in data) {
|
||||
Map<String, dynamic> cat = jsonDecode(value);
|
||||
//Debug.Log(catData);
|
||||
await cacheDb.rawInsert("INSERT OR REPLACE INTO Todos (id, ${Todo.colCat},${Todo.colMetadata},${Todo.colDueDate},${Todo.colNotificationTime}) "
|
||||
"VALUES ('${cat['id'].toString().replaceAll("'", "''")}', '${cat['task_id']}', '${cat['metadata'].toString().replaceAll("'", "''")}', '${cat['due_date']}', '${cat['notification_time']}') ");
|
||||
"VALUES ('${cat['id'].toString().replaceAll("'", "''")}', '${cat['task_id']}', '${cat['metadata'].toString().replaceAll(
|
||||
"'", "''")}', '${cat['due_date']}', '${cat['notification_time']}') ");
|
||||
}
|
||||
} catch (e) {
|
||||
Debug.LogError("Error while cats $e");
|
||||
}else{
|
||||
Debug.Log('Empty Todos');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tasktracker/Analytics.dart';
|
||||
import 'package:tasktracker/Categories.dart';
|
||||
import 'package:tasktracker/Journal.dart';
|
||||
import 'package:tasktracker/Projects.dart';
|
||||
@@ -114,7 +115,8 @@ class MyApp extends StatelessWidget {
|
||||
'/Settings': (context) => const SettingsPage(),
|
||||
'/Projects':(context)=> const Projects(),
|
||||
'/Journal': (context)=> const JournalPage(),
|
||||
'/Todos':(context)=> const TodosPage()
|
||||
'/Todos':(context)=> const TodosPage(),
|
||||
'/Analytics':(context)=> const AnalyticsPage()
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -251,10 +253,11 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
refreshSub = User.refreshStream.stream.listen((value) {
|
||||
print("Streaming refresh : $value");
|
||||
if(value){
|
||||
Dialogs.waiting("Syncing...");
|
||||
// Dialogs.waiting("Syncing...");
|
||||
print("Opening progress dialog");
|
||||
}else{
|
||||
Dialogs.hide();
|
||||
// Dialogs.hide();
|
||||
// Dialogs.hide();
|
||||
print("Closing progress dialog");
|
||||
}
|
||||
});
|
||||
@@ -661,7 +664,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
),
|
||||
)),
|
||||
),
|
||||
Container(
|
||||
if(relativeTodos.isNotEmpty)Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Card(
|
||||
color: Colors.white10,
|
||||
@@ -1044,18 +1047,18 @@ Drawer navDrawer(BuildContext context, int pageIndex) {
|
||||
Navigator.of(context).pushReplacementNamed('/home');
|
||||
},
|
||||
),
|
||||
// ListTile(
|
||||
// selected: (pageIndex == 1),
|
||||
// title: Text('Analytics'),
|
||||
// leading: Icon(Icons.analytics_outlined,
|
||||
// color: Theme.of(context).primaryColor),
|
||||
// onTap: () {
|
||||
// if (pageIndex == 1) {
|
||||
// return;
|
||||
// }
|
||||
// // Navigator.of(context).pushReplacementNamed('/');
|
||||
// },
|
||||
// ),
|
||||
ListTile(
|
||||
selected: (pageIndex == 1),
|
||||
title: Text('Analytics'),
|
||||
leading: Icon(Icons.analytics_outlined,
|
||||
color: Theme.of(context).primaryColor),
|
||||
onTap: () {
|
||||
if (pageIndex == 1) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pushReplacementNamed('/Analytics');
|
||||
},
|
||||
),
|
||||
Divider(),
|
||||
ListTile(
|
||||
selected: (pageIndex == 2),
|
||||
|
||||
Reference in New Issue
Block a user