import 'dart:async'; import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:intl/intl.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tasktracker/NewProject.dart'; import 'package:tasktracker/NotificationsManager.dart'; import 'main.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'Data.dart'; import 'package:sqflite/sqflite.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart' as SqlFF; import 'package:path_provider/path_provider.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:sqflite_common/sqlite_api.dart'; import 'Tasks.dart'; import 'Dialogs.dart'; bool cacheEnabled = true; late http.Response loginResponse; late var cacheDb; late String username; List categories = []; List taskTypes = []; List activities = []; List projects = []; bool offline = true; bool registered = false; StreamController refreshStream = StreamController.broadcast(); Future login(String _username, String password) async { final prefs = await SharedPreferences.getInstance(); username = _username; var device_id = await Settings.UUID(); try { loginResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/login.php'), body: {"username": _username, "password": password, "device_id": device_id})); if (loginResponse.body.toLowerCase().contains("success")) { offline = false; username = _username; registered = loginResponse.body.toLowerCase().contains("register"); print("registered : $registered"); if (registered) { prefs.setBool("registered", true); } } } catch (e) { print("Error while login $e"); } return loginResponse; } Future initUserData() async { if (cacheEnabled) { await initCacheDatabase(); } await refreshUserData(); BuildBridgeToServer(); print('Initializing UserData...'); if (cacheEnabled) { // if (Platform.isAndroid || Platform.isIOS) { // Connectivity().onConnectivityChanged.listen((result) { // offline = (result == ConnectivityResult.none); // if (!offline) { // UserOperations.executeQueries(); // refreshUserData(); // } // }); // } } } Future BuildBridgeToServer() async{ final prefs = await SharedPreferences.getInstance(); while(true){ await UserOperations.executeQueries(); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/bridge.php'), body: {"username": username})); print("bridge retreive (try): ${response.body}"); List data = response.body.split(","); print('Update :\nactivities_rev=${data[0]} tasks_rev=${data[1]} cats_rev=${data[2]} projects_rev=${data[3]}'); if(data[4].contains('')){ List ongoingData = data[4].split(""); if(!prefs.containsKey('current_activity')) { StartActivityTimer(ongoingData[0], ongoingData[1], DateTime.parse(ongoingData[2])); } }else{ CancelOngoingActivity(); } if(prefs.containsKey('rev')){ if(prefs.getString('rev') == response.body){ print('We are on the same page'); }else{ print('Gotta update'); await refreshUserData(); prefs.setString('rev',response.body); } }else{ prefs.setString('rev', response.body); await refreshUserData(); } }catch(e){ print("Error with bridge : $e"); } await Future.delayed(Duration(seconds: 5)); } } bool m_refreshing = false; Future refreshUserData({bool forceOffline = false}) async { print('refreshing user data'); if(m_refreshing){ print('Called while refreshing. Return');return; } m_refreshing=true; if(forceOffline) { refreshStream.add(true); categories = await GetCategories(true); taskTypes = await GetTaskTypes(true); activities = await GetActivities(true); projects= await GetProjects(true); refreshStream.add(false); }else{ await updateCatsList(); await updateTasksList(); await updateActList(); await updateProjectsList(); } m_refreshing=false; if (cacheEnabled) { NotificationManager.RescheduleNotifications(); } } Future cacheDbExist() async { if (Platform.isAndroid || Platform.isIOS) { Directory directory = await getApplicationDocumentsDirectory(); return databaseFactory.databaseExists(directory.path + 'cache.db'); } else { Directory directory = await getApplicationDocumentsDirectory(); return SqlFF.databaseFactoryFfi.databaseExists(directory.path + 'cache.db'); } } Future updateCatsList() async { categories = await GetCategories(false); } Future updateTasksList() async { taskTypes = await GetTaskTypes(false); } Future updateActList() async { activities = await GetActivities(false); } Future updateProjectsList() async{ projects = await GetProjects(false); } Future initCacheDatabase() async { Directory directory = await getApplicationDocumentsDirectory(); print('database at ' + directory.path + 'cache.db'); if (Platform.isAndroid || Platform.isIOS) { cacheDb = await openDatabase(directory.path + 'cache.db', version: 1, onCreate: onCacheDatabaseCreate, onUpgrade: onCacheDatabaseUpgrade); } else { cacheDb = await SqlFF.databaseFactoryFfi .openDatabase(directory.path + 'cache.db', options: OpenDatabaseOptions(version: 1, onCreate: onCacheDatabaseCreate)); } await UserOperations.executeQueries(); } void onCacheDatabaseCreate(Database db, int newVersion) async { String CategoriesTableSQL = 'CREATE TABLE Categories(${Category.colCatId} VARCHAR(255) PRIMARY KEY,${Category.colName} TEXT, ${Category.colColor} TEXT, ${Category.colProductive} INTEGER)'; // print(CategoriesTableSQL); await db.execute(CategoriesTableSQL); print("Initiated Categories Table"); String TaskTableSQL = 'CREATE TABLE TaskTypes(id TEXT PRIMARY KEY, ${TaskType.colName} TEXT, ${TaskType.colCategory} TEXT, ' 'FOREIGN KEY (${TaskType.colCategory}) REFERENCES Categories(${Category.colCatId}))'; // print(TaskTableSQL); await db.execute(TaskTableSQL); String ActivityTableSQL = 'CREATE TABLE Activities(id INTEGER PRIMARY KEY AUTOINCREMENT, ${Activity.colType} INT, ${Activity.colStartTime} DATETIME, ${Activity.colEndTime} DATETIME, ${Activity.colMetadata} TEXT, ' 'FOREIGN KEY (${Activity.colType}) REFERENCES TaskTypes(id))'; // print(ActivityTableSQL); await db.execute(ActivityTableSQL); String ProjectsTableSQL = 'CREATE TABLE Projects(id TEXT PRIMARY KEY, ${Project.colName} TEXT, ${Project.colCat} TEXT, ${Project.colSteps} TEXT, ${Project.colDeadline} DATETIME)'; await db.execute(ProjectsTableSQL); String QueriesTableSQL = 'CREATE TABLE Queries(id INTEGER PRIMARY KEY AUTOINCREMENT, ${Queries.colLink} TEXT,${Queries.colData} TEXT)'; // print(QueriesTableSQL); await db.execute(QueriesTableSQL); final prefs = await SharedPreferences.getInstance(); if (prefs.getBool("registered") ?? false) { addInitialDataToCache(); prefs.setBool("registered", false); } // GetCategories(); } Future addInitialDataToCache() async { Dialogs.syncingMessage= "Adding initial data"; print("adding init data"); await Future.delayed(const Duration(seconds: 1)); //Insert Initial Entries for (Category element in InitialData.getCategories(username)) { await UserOperations.addCategory(element.name, element.color, element.productive, bulk: true); } Dialogs.syncingMessage= "Just a minute"; for (TaskType element in InitialData.getTaskTypes(username)) { await UserOperations.addTaskType(element.name, element.category, bulk: true); // Map data = { // TaskType.colName: element.name, // TaskType.colCategory: element.category // }; // await cacheDb.insert('TaskTypes', data); } Dialogs.syncingMessage= "Syncing"; await UserOperations.executeQueries(); // await refreshUserData(); } void onCacheDatabaseUpgrade(Database db, int oldVersion, int newVersion) async { //ValidateCacheDB(); print('Upgrading CacheDB from ver.$oldVersion to ver.$newVersion'); } Future> GetCategories(bool forceOffline) async { if (cacheEnabled) { List _categories = []; if (offline || forceOffline) { //Retreive from cacheDB } else { //Check if server got updated, If not go for cache var android_id = await Settings.UUID(); //Validate device_id to check updates bool catsUpdated = false; // try { // http.Response update_response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/check_update.php'), body: {"username": username, "device_id": android_id})); // final data = update_response.body.split(','); // catsUpdated = data[0] == '1'; // } catch (e) { // print(e); // } print("Need to update : ${!catsUpdated}"); //Update CacheDB if (!catsUpdated) { await UpdateCategoriesFromServer(); } } List cats = await cacheDb.query('Categories'); print(cats.length); for (Map element in cats) { String? catName = element[Category.colName].toString(); String? catColor = element[Category.colColor].toString(); String? catProductive = element[Category.colProductive].toString(); if (catName == null || catColor == null || catProductive == null) { print("Something is null!"); print("name:{$catName}, color:{$catColor}, prod:{$Category.colProductive}"); continue; } // print("name:{$catName}, color:{$catColor}, prod:{$catProductive}"); _categories.add(Category(username + catName, catName, catColor, ParseBool(catProductive))); } categories = _categories; } else { print("NC: Updating Categories as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_categories.php'), body: {"username": username, "device_id": await Settings.UUID()})); print(response.body); List data = response.body.split(""); List _categories = []; for (var value in data) { Map cat = jsonDecode(value); //print(catData); _categories.add(Category(cat['category_id'], cat['name'], cat['color'], ParseBool(cat['productive']))); } categories = _categories; } catch (e) { print("Error while cats NC: $e"); } } return categories; } Future UpdateCategoriesFromServer() async { print("Updating Categories as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_categories.php'), body: {"username": username, "device_id": await Settings.UUID()})); print(response.body); List data = response.body.split(""); // await cacheDb.delete("Categories"); for (var value in data) { Map cat = jsonDecode(value); //print(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']}') "); } } catch (e) { print("Error while cats $e"); } } Future> GetTaskTypes(bool forceOffline) async { if (cacheEnabled) { List _taskTypes = []; if (offline || forceOffline) { //Retreive from cacheDB } else { //Check if server got updated, If not go for cache var android_id = await Settings.UUID(); bool updated = false; // try { // //Validate device_id to check updates // http.Response update_response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/check_update.php'), body: {"username": username, "device_id": android_id})); // final data = update_response.body.split(','); // updated = data[1] == '1'; // } catch (e) { // print(e); // } print("Need to update : ${!updated}"); //Update CacheDB if (!updated) { await UpdateTaskTypesFromServer(); } } await Future.delayed(Duration(seconds: 1)); List cats = await cacheDb.query('TaskTypes'); print(cats.length); for (Map element in cats) { String? id = element[TaskType.colId].toString(); String? name = element[TaskType.colName].toString(); String? category = element[TaskType.colCategory].toString(); Category? cat = await getCatFromId(category); if (id == null || name == null || category == null) { print("Something is null!"); print("name:{$name}, cat:{$category}, prod:{$id}"); continue; } // print("name:{$name}, cat:{$category}, prod:{$id}"); _taskTypes.add(TaskType(id, name, category, cat)); } taskTypes = _taskTypes; } else { List _taskTypes = []; print("NC: Updating TaskTypes as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_taskTypes.php'), body: {"username": username, "device_id": await Settings.UUID()})); print("taskType retreive (try): ${response.body}"); List data = response.body.split(""); for (var value in data) { Map data = jsonDecode(value); Category? cat = await getCatFromId(data['category_id']); _taskTypes.add(TaskType(data['task_id'], data['name'], data['category_id'], cat)); //print(cat); } }catch(e){ print("Error while tasks NC $e"); } taskTypes = _taskTypes; } return taskTypes; } Future UpdateTaskTypesFromServer() async { // await GetCategories(true); print("Updating TaskTypes as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_taskTypes.php'), body: {"username": username, "device_id": await Settings.UUID()})); print(response.body); List data = response.body.split(""); await cacheDb.delete("TaskTypes"); for (var value in data) { Map cat = jsonDecode(value); //print(cat); await cacheDb.rawInsert("INSERT OR REPLACE INTO TaskTypes (${TaskType.colId},${TaskType.colName},${TaskType.colCategory}) " "VALUES ('${cat['task_id']}','${cat['name']}','${cat['category_id']}') "); print(await cacheDb.query("TaskTypes")); } } catch (e) { print("Error while tasks $e"); } } void StartActivityTimer(String taskType, String metadata, DateTime startTime) async{ final prefs = await SharedPreferences.getInstance(); prefs.setString('current_activity', "$taskType$metadata${UserOperations.dFormat.format(startTime)}"); NotificationManager.RescheduleNotifications(); UserOperations.startOngoing(prefs.getString('current_activity')!); } Future?> getOngoingData() async{ final prefs = await SharedPreferences.getInstance(); if(prefs.containsKey('current_activity')){ List data = []; try{ data = prefs.getString('current_activity')!.split(''); return data; }catch(e){ } }else{ } } void StopActivityTimer() async{ final prefs = await SharedPreferences.getInstance(); try { List data = prefs.getString('current_activity')!.split(""); UserOperations.addActivity(data[0], DateTime.parse(data[2]), DateTime.now(),metadata: data[1]); }catch(e){} prefs.remove('current_activity'); UserOperations.stopOngoing(); } void CancelOngoingActivity() async{ final prefs = await SharedPreferences.getInstance(); prefs.remove('current_activity'); UserOperations.stopOngoing(); } Future> GetActivities(bool forceOffline) async { if (cacheEnabled) { List _activities = []; if (offline || forceOffline) { //Retreive from cacheDB print('offline, refreshing activities'); } else { //Check if server got updated, If not go for cache var android_id = await Settings.UUID(); bool updated = false; // try { // //Validate device_id to check updates // http.Response update_response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/check_update.php'), body: {"username": username, "device_id": android_id})); // final data = update_response.body.split(','); // updated = data[2] == '1'; // } catch (e) { // print(e); // } print("Need to update activities : ${!updated}"); //Update CacheDB if (!updated) { await UpdateActivitiesFromServer(); } } List cats = await cacheDb.rawQuery('SELECT * FROM Activities ORDER BY ${Activity.colStartTime} DESC'); print(cats.length); for (Map element in cats) { int? id = element['id']; String? type = element[Activity.colType].toString(); String? startTime = element[Activity.colStartTime].toString(); String? endTime = element[Activity.colEndTime].toString(); String? metadata = element[Activity.colMetadata].toString(); TaskType? taskType = await getTaskFromId(type); if (type == null || startTime == null || endTime == null || taskType == null) { print("Something is null!\ntype:${type == null}, startTime:${startTime == null}, eTime:${endTime == null}, taskType${taskType == null}"); print("TaskType:{$type}, Start Time:{$startTime}, endTime:{$endTime}, metadata:${metadata}"); continue; } //print("TaskType:{$type}, Start Time:{$startTime}, endTime:{$endTime}, metadata:${metadata}"); DateTime sTime = DateTime.parse(startTime); DateTime eTime = DateTime.parse(endTime); if (eTime.day != sTime.day) { DateTime midnight = DateTime(eTime.year, eTime.month, eTime.day, 0, 0, 0); int firstHalf = eTime.difference(midnight).inMinutes; int secondHalf = midnight.difference(sTime).inMinutes; // print("${taskType.name} first half : $firstHalf -> second half: $secondHalf"); if (firstHalf > 1) { _activities.add(Activity(taskType, midnight, eTime, metadata: metadata, tStartTime: sTime)); } if (secondHalf > 1) { _activities.add(Activity(taskType, sTime, midnight, metadata: metadata, tEndTime: eTime)); } } else { _activities.add(Activity(taskType, DateTime.parse(startTime), DateTime.parse(endTime), metadata: metadata)); } } activities = _activities; } else { print("NC :Updating Activities as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_activities.php'), body: {"username": username, "device_id": await Settings.UUID()})); print("Activity response: ${response.body}"); List _activities = []; if (response.body.contains("{")) { List data = response.body.split(""); for (var value in data) { Map cat = jsonDecode(value); int? id = cat['id']; String? type = cat['task_id'].toString(); String? startTime = cat['sTime'].toString(); String? endTime = cat['eTime'].toString(); String? metadata = cat['metadata']; TaskType? taskType = await getTaskFromId(type); if (taskType == null) { print('null found'); continue; } //print("TaskType:{$type}, Start Time:{$startTime}, endTime:{$endTime}, metadata:${metadata}"); DateTime sTime = DateTime.parse(startTime); DateTime eTime = DateTime.parse(endTime); if (eTime.day != sTime.day) { DateTime midnight = DateTime(eTime.year, eTime.month, eTime.day, 0, 0, 0); int firstHalf = eTime.difference(midnight).inMinutes; int secondHalf = midnight.difference(sTime).inMinutes; // print("${taskType.name} first half : $firstHalf -> second half: $secondHalf"); if (firstHalf > 1) { _activities.add(Activity(taskType, midnight, eTime, metadata: metadata, tStartTime: sTime)); } if (secondHalf > 1) { _activities.add(Activity(taskType, sTime, midnight, metadata: metadata, tEndTime: eTime)); } } else { _activities.add(Activity(taskType, DateTime.parse(startTime), DateTime.parse(endTime), metadata: metadata)); } } activities = _activities.reversed.toList(); } else { print("No activities for now"); } } catch (e) { print("Error : $e @ updating activities"); print("Error while acts $e"); } } return activities; } Future UpdateActivitiesFromServer() async { print("Updating Activities as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_activities.php'), body: {"username": username, "device_id": await Settings.UUID()})); await cacheDb.rawDelete("DELETE FROM Activities"); print('Truncate Activity Table before'); print("Activity response: ${response.body}"); if (response.body.contains("{")) { List data = response.body.split(""); for (var value in data) { Map cat = jsonDecode(value); //print(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']}') "); } } else { print("No activities for now"); } } catch (e) { print("Error : $e @ updating activities"); print("Error while acts $e"); } } Future> GetProjects(bool forceOffline) async { if (cacheEnabled) { List _projects = []; if (offline || forceOffline) { //Retreive from cacheDB print('offline, refreshing projects'); } else { //Check if server got updated, If not go for cache var android_id = await Settings.UUID(); bool updated = false; print("Need to update activities : ${!updated}"); //Update CacheDB if (!updated) { await UpdateProjectsFromServer(); } } List cats = await cacheDb.rawQuery('SELECT * FROM Projects'); print(cats.length); for (Map element in cats) { String? name = element[Project.colName]; String? category = element[Project.colCat]; String? stepsJson = element[Project.colSteps]; String? deadline = element[Project.colDeadline]; if (name == null || category == null || stepsJson == null || deadline == null) { print("Something is null!\nname:${name == null}, cat:${category == null}, steps:${stepsJson == null}, deadline${deadline == null}"); print("TaskType:{$name}, Start Time:{$category}, endTime:{$stepsJson}, metadata:${deadline}"); continue; } Category? cat = await getCatFromId(category); if(cat==null){print('couldnt find cat');continue;} print('steps : $stepsJson'); List _steps = jsonDecode(stepsJson); List steps = []; _steps.forEach((element) { ProjectStep step = ProjectStep.fromJson(element); steps.add(step); print(element); }); // print(steps); _projects.add(Project(name.replaceAll(username, ""),category,steps,DateTime.parse(deadline),cat: cat)); } projects = _projects; } else { print("NC :Updating Projects as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_projects.php'), body: {"username": username, "device_id": await Settings.UUID()})); print("Activity response: ${response.body}"); List _projects = []; if (response.body.contains("{")) { List data = response.body.split(""); for (var value in data) { Map cat = jsonDecode(value); int? id = cat['id']; String? type = cat['task_id'].toString(); String? startTime = cat['sTime'].toString(); String? endTime = cat['eTime'].toString(); String? metadata = cat['metadata']; TaskType? taskType = await getTaskFromId(type); if (taskType == null) { print('null found'); continue; } } projects = _projects; } else { print("No activities for now"); } } catch (e) { print("Error : $e @ updating activities"); print("Error while acts $e"); } } return projects; } Future UpdateProjectsFromServer() async { print("Updating Projects as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_projects.php'), body: {"username": username, "device_id": await Settings.UUID()})); await cacheDb.rawDelete("DELETE FROM Projects"); print('Truncate Projects Table before'); print("Projects response: ${response.body}"); if (response.body.contains("{")) { List data = response.body.split(""); for (var value in data) { Map cat = jsonDecode(value); print('project data'); print(cat); await cacheDb.rawInsert( "INSERT OR REPLACE INTO Projects (${Project.colName}, ${Project.colCat}, ${Project.colSteps}, ${Project.colDeadline}) " "VALUES ('${cat['name']}', '${cat['category']}', '${cat['steps']}', '${cat['deadline']}')"); } } else { print("No activities for now"); } } catch (e) { print("Error : $e @ updating activities"); print("Error while acts $e"); } } Future getTaskFromId(String taskId) async { // await GetTaskTypes(false); TaskType? cat = null; for (var element in taskTypes) { if (element.id == taskId) { cat = element; cat?.cat = await getCatFromId((cat?.category ?? '')); } } if (cat == null) { print('Got null tasktype for ${taskId} after searching on ${taskTypes.length}'); } return cat; } Future getCatFromId(String catId) async { // await GetTaskTypes(false); Category? cat = null; for (var element in categories) { if (element.category_id == catId) { cat = element; } } return cat; } //Helpers class Helpers { Future _getId() async { var deviceInfo = DeviceInfoPlugin(); if (Platform.isIOS) { // import 'dart:io' var iosDeviceInfo = await deviceInfo.iosInfo; return iosDeviceInfo.identifierForVendor; // unique ID on iOS } else { var androidDeviceInfo = await deviceInfo.androidInfo; return androidDeviceInfo.androidId; // unique ID on Android } } } bool ParseBool(obj) { return obj.toString().toLowerCase() == "true" || obj.toString() == "1"; } class UserOperations { static DateFormat dFormat = DateFormat("yyyy-MM-dd HH:mm:ss"); static Future addCategory(String name, String color, bool productive, {bool bulk = false}) async { Map queryBody = { 'username': username, 'device_id': await Settings.UUID(), 'name': name, 'color': color, 'productive': productive ? '1' : '0' }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'add_category', Queries.colData: jsonEncode(queryBody)}; print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); //update Cache Map data = { Category.colCatId: username + name, Category.colName: name, Category.colColor: color, Category.colProductive: productive }; await cacheDb.insert('Categories', data); await refreshUserData(forceOffline: true); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/add_category.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error editing acti $e}'); } //executeQueries(); } if (!bulk) { //Add to server and refresh Cache await executeQueries(); } } static Future addTaskType(String name, String category, {bool bulk = false}) async { Map queryBody = { 'id': username + name, 'username': username, 'device_id': await Settings.UUID(), 'name': name, 'category': username + category }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'add_taskType', Queries.colData: jsonEncode(queryBody)}; print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); //update Cache Map data = {TaskType.colId: username + name, Category.colName: name, Category.colCatId: username + category}; await cacheDb.insert('TaskTypes', data); await refreshUserData(forceOffline: true); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/add_taskType.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error editing acti $e}'); } } if (!bulk) { //Add to server and refresh Cache await executeQueries(); } } static Future addActivity(String type, DateTime sTime, DateTime eTime, {String metadata = 'null', bool bulk = false, Function(int)? onOverlap}) async { Map queryBody = { 'username': username, 'device_id': await Settings.UUID(), 'type': username + type, 'sTime': dFormat.format(sTime), 'eTime': dFormat.format(eTime), 'metadata': metadata }; Map query = {Queries.colLink: 'add_activity', Queries.colData: jsonEncode(queryBody)}; if (cacheEnabled) { //Check for timeoverlapse activities = await GetActivities(true); int? overlapCount = Sqflite.firstIntValue(await cacheDb.rawQuery( "SELECT COUNT(*) FROM Activities WHERE (((${Activity.colStartTime} < datetime('$sTime')) AND ((${Activity.colEndTime} > datetime('$eTime')) OR (${Activity.colEndTime} < datetime('$eTime') AND ${Activity.colEndTime} > datetime('$sTime')))) OR (${Activity.colStartTime} > datetime('$sTime') AND ${Activity.colStartTime} < datetime('$eTime')) OR (${Activity.colStartTime}=datetime('$sTime') AND ${Activity.colEndTime}=datetime('$eTime')))")); print("ActivityOverlaps: $overlapCount"); if (overlapCount! > 0) { onOverlap!(overlapCount); return; } if (metadata.length > 0) {} //Add Query print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); //update Cache Map data = { Activity.colType: username + type, Activity.colStartTime: dFormat.format(sTime), Activity.colEndTime: dFormat.format(eTime), Activity.colMetadata: metadata }; await cacheDb.insert('Activities', data); await refreshUserData(forceOffline: true); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/add_activity.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error adding player $e}'); } } if (!bulk) { //Add to server and refresh Cache await executeQueries(); } } static Future editActivity(DateTime init_sTime, DateTime init_eTime, String type, DateTime sTime, DateTime eTime, {String metadata = 'null', bool bulk = false, Function(int)? onOverlap}) async { Map queryBody = { 'username': username, 'device_id': await Settings.UUID(), 'type': username + type, 'init_sTime': dFormat.format(init_sTime), 'init_eTime': dFormat.format(init_eTime), 'sTime': dFormat.format(sTime), 'eTime': dFormat.format(eTime), 'metadata': metadata }; Map query = {Queries.colLink: 'edit_activity', Queries.colData: jsonEncode(queryBody)}; if (cacheEnabled) { //Check for timeoverlapse activities = await GetActivities(true); int? overlapCount = Sqflite.firstIntValue(await cacheDb.rawQuery( "SELECT COUNT(*) FROM Activities WHERE (((${Activity.colStartTime} < datetime('$sTime')) AND ((${Activity.colEndTime} > datetime('$eTime')) OR (${Activity.colEndTime} < datetime('$eTime') AND ${Activity.colEndTime} > datetime('$sTime')))) OR (${Activity.colStartTime} > datetime('$sTime') AND ${Activity.colStartTime} < datetime('$eTime')) OR (${Activity.colStartTime}=datetime('$sTime') AND ${Activity.colEndTime}=datetime('$eTime'))) AND ${Activity.colStartTime}!=datetime('${init_sTime}') AND ${Activity.colEndTime} != datetime('${init_eTime}')")); print("ActivityOverlaps: $overlapCount"); if (overlapCount! > 0) { onOverlap!(overlapCount); return; } if (metadata.length > 0) {} //Add Query print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); //update Cache // Map data = {Activity.colType: username + type, Activity.colStartTime: dFormat.format(sTime), Activity.colEndTime: dFormat.format(eTime), Activity.colMetadata: metadata}; // String updateActQuery = "UPDATE Activities SET ${Activity.colType}="; // await cacheDb.insert('Activities', data); await refreshUserData(forceOffline: true); } else { // queries.add(Queries('edit_activity', jsonEncode(queryBody))); try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/edit_activity.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error editing acti $e}'); } } if (!bulk) { //Add to server and refresh Cache await executeQueries(); } } static Future startOngoing(String activityData) async { Map queryBody = { 'username': username, 'current_activity': activityData, }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'start_ongoing', Queries.colData: jsonEncode(queryBody)}; print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/start_ongoing.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error adding ongoing $e}'); } } await executeQueries(); } static Future stopOngoing() async { Map queryBody = { 'username': username, }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'stop_ongoing', Queries.colData: jsonEncode(queryBody)}; print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/stop_ongoing.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error adding ongoing $e}'); } } await executeQueries(); } static Future addProject(String name, String category, List steps, DateTime deadline) async { Map queryBody = { 'name': username + name, 'username': username, 'device_id': await Settings.UUID(), 'category_id': username + category, 'steps': jsonEncode(steps), 'deadline': DateFormat("yyyy-MM-dd").format(deadline) }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'add_project', Queries.colData: jsonEncode(queryBody)}; print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); //update Cache Map data = {Project.colName: username+name, Project.colCat: category, Project.colSteps: jsonEncode(steps), Project.colDeadline: deadline.toString()}; await cacheDb.insert('Projects', data); await refreshUserData(forceOffline: true); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/add_project.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error adding prjct $e}'); } } await executeQueries(); } static Future deleteTask(String name, {bulk = false}) async { Map queryBody = { 'id': username + name, 'username': username, 'device_id': await Settings.UUID(), }; //Add Query Map query = {Queries.colLink: 'delete_taskType', Queries.colData: jsonEncode(queryBody)}; print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); if (cacheEnabled) { await cacheDb.insert('Queries', query); //update Cache Map data = { TaskType.colId: username + name, Category.colName: name, }; await cacheDb.rawDelete("DELETE FROM TaskTypes WHERE id='${username + name}'"); await refreshUserData(forceOffline: true); //Add to server and refresh Cache } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/delete_taskType.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error editing acti $e}'); } } if (!bulk) { await executeQueries(); } } static Future deleteCategory(String name, {bulk = false}) async { Map queryBody = { 'id': username + name, 'username': username, 'device_id': await Settings.UUID(), }; //Add Query Map query = {Queries.colLink: 'delete_category', Queries.colData: jsonEncode(queryBody)}; print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); if (cacheEnabled) { await cacheDb.insert('Queries', query); //update Cache Map data = { TaskType.colId: username + name, Category.colName: name, }; await cacheDb.rawDelete("DELETE FROM Categories WHERE ${Category.colCatId}='${username + name}'"); await refreshUserData(forceOffline: true); //Add to server and refresh Cache } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/delete_category.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error editing acti $e}'); } } if (!bulk) { await executeQueries(); } } static Future deleteActivity(Activity activity, {bulk = false}) async { Map queryBody = { 'username': username, 'device_id': await Settings.UUID(), 'sTime': activity.trueStartTime.toString(), 'eTime': activity.trueEndTime.toString(), }; //Add Query Map query = {Queries.colLink: 'delete_activity', Queries.colData: jsonEncode(queryBody)}; print("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); if (cacheEnabled) { await cacheDb.insert('Queries', query); //update Cache String deleteQuery = "DELETE FROM Activities WHERE ${Activity.colStartTime}=datetime('${dFormat.format(activity.trueStartTime)}') AND ${Activity.colEndTime}=datetime('${dFormat.format(activity.trueEndTime)}')"; print("delteQuery : $deleteQuery"); await cacheDb.rawDelete(deleteQuery); await refreshUserData(forceOffline: true); //Add to server and refresh Cache } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/delete_activity.php'), body: queryBody)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { print('NC: Error editing acti $e}'); } } if (!bulk) { await executeQueries(); } } static Future executeQueries() async { if (cacheEnabled) { if (offline) { print("Cannot executre queries, Offline!"); return; } List> queries = await cacheDb.query('Queries'); for (Map element in queries) { int id = int.parse(element['id'].toString()); String? file = element[Queries.colLink].toString(); String? data = element[Queries.colData].toString(); if (file == null || data == null) { print("Null query, Ignoring..."); continue; } print("Query[\n file:$file, \ndata:$data]"); //Execute the http here Map body = jsonDecode(data); try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/$file.php'), body: body)); print("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { await cacheDb.rawDelete('DELETE FROM Queries WHERE id=$id'); } offline = false; } catch (e) { print("Error while query $e"); } } //await refreshUserData(); } else { await refreshUserData(); print('Trying to execute queries in no cahce mode, We dont do that here'); } } }