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 'DebugHelper.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 = []; List journal = []; List todos = []; 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"); Debug.Log("registered : $registered"); if (registered) { prefs.setBool("registered", true); } } } catch (e) { Debug.LogError("Error while login $e"); } return loginResponse; } Future initUserData() async { if (cacheEnabled) { await initCacheDatabase(); } await refreshUserData(); BuildBridgeToServer(); Debug.Log('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})); Debug.LogResponse("${response.body}",src: 'bridge'); List data = response.body.split(","); Debug.LogResponse('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 { if (prefs.containsKey('current_activity')) CancelOngoingActivity(); } if (prefs.containsKey('rev')) { if (prefs.getString('rev') == response.body) { Debug.Log('We are on the same page'); } else { Debug.Log('Gotta update'); await refreshUserData(); prefs.setString('rev', response.body); } } else { prefs.setString('rev', response.body); await refreshUserData(); } } catch (e) { Debug.LogError("Error with bridge : $e"); } await Future.delayed(Duration(seconds: 5)); } } bool m_refreshing = false; Future refreshUserData({bool forceOffline = false}) async { Debug.Log('refreshing user data'); if (m_refreshing) { Debug.LogError('Called while refreshing. Return'); return; } m_refreshing = true; if (forceOffline) { refreshStream.add(true); categories = await GetCategories(true); projects = await GetProjects(true); taskTypes = await GetTaskTypes(true); activities = await GetActivities(true); journal = await GetJournals(true); todos = await GetTodos(true); refreshStream.add(false); } else { categories = await GetCategories(false); projects = await GetProjects(false); taskTypes = await GetTaskTypes(false); activities = await GetActivities(false); journal = await GetJournals(false); todos= await GetTodos(false); } 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(); Debug.LogResponse('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)'; // Debug.Log(CategoriesTableSQL); await db.execute(CategoriesTableSQL); Debug.Log("Initiated Categories Table"); String TaskTableSQL = 'CREATE TABLE TaskTypes(id TEXT PRIMARY KEY, ${TaskType.colName} TEXT, ${TaskType.colCategory} TEXT, ${TaskType.colRelatedProject} TEXT, ' 'FOREIGN KEY (${TaskType.colCategory}) REFERENCES Categories(${Category.colCatId}))'; // Debug.Log(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))'; // Debug.Log(ActivityTableSQL); await db.execute(ActivityTableSQL); String ProjectsTableSQL = 'CREATE TABLE Projects(id TEXT PRIMARY KEY, ${Project.colName} TEXT, ${Project.colCat} TEXT, ${Project.colSteps} TEXT, ${Project.colEta} INT, ${Project.colDeadline} DATETIME)'; await db.execute(ProjectsTableSQL); String JournalTableSQL = 'CREATE TABLE Journal(id TEXT PRIMARY KEY, ${Journal.colTitle} TEXT, ${Journal.colDescription})'; await db.execute(JournalTableSQL); String TodoTableSQL = 'CREATE TABLE Todos(id TEXT PRIMARY KEY, ${Todo.colCat} TEXT, ${Todo.colMetadata} TEXT, ${Todo.colDueDate} DATE, ${Todo.colNotificationTime} DATETIME)'; await db.execute(TodoTableSQL); String QueriesTableSQL = 'CREATE TABLE Queries(id INTEGER PRIMARY KEY AUTOINCREMENT, ${Queries.colLink} TEXT,${Queries.colData} TEXT)'; 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"; Debug.Log("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(); Debug.LogResponse('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) { // Debug.Log(e); // } Debug.Log("Need to update : ${!catsUpdated}"); //Update CacheDB if (!catsUpdated) { await UpdateCategoriesFromServer(); } } List cats = await cacheDb.query('Categories'); Debug.Log('categories :${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) { Debug.LogError("Something is null!"); Debug.LogError("name:{$catName}, color:{$catColor}, prod:{$Category.colProductive}"); continue; } // Debug.Log("name:{$catName}, color:{$catColor}, prod:{$catProductive}"); _categories.add(Category(username + catName, catName, catColor, ParseBool(catProductive))); } categories = _categories; } else { Debug.Log("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()})); Debug.LogResponse(response.body,src:'get_categories'); List data = response.body.split(""); List _categories = []; for (var value in data) { Map cat = jsonDecode(value); _categories.add(Category(cat['category_id'], cat['name'], cat['color'], ParseBool(cat['productive']))); } categories = _categories; } catch (e) { Debug.LogError("Error while cats NC: $e"); } } return categories; } Future UpdateCategoriesFromServer() async { Debug.Log("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()})); Debug.LogResponse(response.body); List data = response.body.split(""); await cacheDb.delete("Categories"); for (var value in data) { Map 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']}') "); } } catch (e) { Debug.LogError("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) { // Debug.Log(e); // } Debug.Log("Need to update : ${!updated}"); //Update CacheDB if (!updated) { await UpdateTaskTypesFromServer(); } } await Future.delayed(Duration(seconds: 1)); List cats = await cacheDb.query('TaskTypes'); Debug.Log(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(); String? related_project = element[TaskType.colRelatedProject].toString(); Category? cat = await getCatFromId(category); if (id == null || name == null || category == null) { Debug.LogError("Something is null!"); Debug.LogError("name:{$name}, cat:{$category}, prod:{$id}"); continue; } Project? relatedProject; if (related_project.isNotEmpty) { relatedProject = await getProjectFromId(related_project); Debug.Log('got a tasktype with project'); } // Debug.Log("name:{$name}, cat:{$category}, prod:{$id}"); _taskTypes.add(TaskType(id, name, category, cat: cat, relatedProject: relatedProject)); } taskTypes = _taskTypes; } else { List _taskTypes = []; Debug.Log("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()})); Debug.LogResponse("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: cat, relatedProject: data['related_project'])); //Debug.Log(cat); } } catch (e) { Debug.LogError("Error while tasks NC $e"); } taskTypes = _taskTypes; } return taskTypes; } Future UpdateTaskTypesFromServer() async { // await GetCategories(true); Debug.Log("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()})); Debug.LogResponse(response.body); List data = response.body.split(""); await cacheDb.delete("TaskTypes"); for (var value in data) { Map 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")); } } catch (e) { Debug.LogError("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 Debug.Log('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) { // Debug.Log(e); // } Debug.Log("Need to update activities : ${!updated}"); //Update CacheDB if (!updated) { await UpdateActivitiesFromServer(); } } List cats = await cacheDb.rawQuery('SELECT * FROM Activities ORDER BY ${Activity.colStartTime} DESC'); Debug.Log(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) { Debug.LogError("Something is null!\ntype:${type == null}, startTime:${startTime == null}, eTime:${endTime == null}, taskType${taskType == null}"); Debug.LogError("TaskType:{$type}, Start Time:{$startTime}, endTime:{$endTime}, metadata:${metadata}"); continue; } //Debug.Log("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; // Debug.Log("${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 { Debug.Log("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()})); Debug.LogResponse("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) { Debug.LogError('null found'); continue; } //Debug.Log("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; // Debug.Log("${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 { Debug.LogError("No activities for now"); } } catch (e) { Debug.LogError("Error while acts $e"); } } return activities; } Future UpdateActivitiesFromServer() async { Debug.Log("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"); Debug.Log('Truncate Activity Table before'); // Debug.Log("Activity response: ${response.body}"); if (response.body.contains("{")) { List data = response.body.split(""); for (var value in data) { Map 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> GetProjects(bool forceOffline) async { if (cacheEnabled) { List _projects = []; if (offline || forceOffline) { //Retreive from cacheDB Debug.Log('offline, refreshing projects'); } else { //Check if server got updated, If not go for cache var android_id = await Settings.UUID(); bool updated = false; Debug.Log("Need to update activities : ${!updated}"); //Update CacheDB if (!updated) { await UpdateProjectsFromServer(); } } List cats = await cacheDb.rawQuery('SELECT * FROM Projects'); Debug.Log('projects : ${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]; int? eta = element[Project.colEta]; if (name == null || category == null || stepsJson == null || deadline == null || eta == null) { Debug.LogError("Something is null!\nname:${name == null}, cat:${category == null}, steps:${stepsJson == null}, deadline${deadline == null}"); Debug.LogError("TaskType:{$name}, Start Time:{$category}, endTime:{$stepsJson}, metadata:${deadline}"); continue; } Category? cat = await getCatFromId(category); Debug.Log('searching for $category'); if (cat == null) { Debug.LogError('couldnt find cat'); continue; } Debug.LogResponse('steps : $stepsJson'); List _steps = jsonDecode(stepsJson); List steps = []; int m_eta = 0; _steps.forEach((element) { ProjectStep step = ProjectStep.fromJson(element); m_eta += step.eta; steps.add(step); Debug.LogResponse(element); }); eta = (m_eta > 0) ? m_eta : eta; // Debug.Log(steps); _projects.add(Project(name.replaceAll(username, ""), category, steps, eta, DateTime.parse(deadline), cat: cat)); } projects = _projects; } else { Debug.Log("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()})); // Debug.Log("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) { Debug.LogError('null task found'); continue; } } projects = _projects; } else { Debug.Log("No activities for now"); } } catch (e) { Debug.LogError("Error : $e @ updating activities"); Debug.LogError("Error while acts $e"); } } return projects; } Future UpdateProjectsFromServer() async { Debug.Log("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"); Debug.Log('Truncate Projects Table before'); Debug.LogResponse("Projects response: ${response.body}"); if (response.body.contains("{")) { List data = response.body.split(""); for (var value in data) { Map 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"); } } catch (e) { Debug.LogError("Error while acts $e"); } } Future> GetJournals(bool forceOffline) async { if (cacheEnabled) { List _journals = []; if (offline || forceOffline) { //Retreive from cacheDB } else { //Check if server got updated, If not go for cache //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) { // Debug.Log(e); // } //Update CacheDB if (!catsUpdated) { await UpdateJournalsFromServer(); } } List cats = await cacheDb.query('Journal'); Debug.Log(cats.length); for (Map element in cats) { String? id = element['id'].toString(); String? title = element[Journal.colTitle].toString(); String? text = element[Journal.colDescription].toString(); if (id == null || title == null || text == null) { Debug.LogError("Something is null!"); Debug.LogError("id:{$id}, title:{$title}, text:${text}"); continue; } DateTime day = DateTime.parse(id.replaceAll(username, '')); // Debug.Log("name:{$catName}, color:{$catColor}, prod:{$catProductive}"); _journals.add(Journal(id, day, title: title, description: text)); } journal = _journals; } else { Debug.Log("NC: Updating Categories as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_journals.php'), body: {"username": username, "device_id": await Settings.UUID()})); Debug.LogResponse(response.body); List data = response.body.split(""); List _categories = []; for (var value in data) { Map cat = jsonDecode(value); //Debug.Log(catData); _categories .add(Journal(cat['id'], DateTime.parse(cat['id'].toString().replaceAll(username, '')), title: cat['title'], description: cat['text'])); } journal = _categories; } catch (e) { Debug.LogError("Error while cats NC: $e"); } } journal.sort((a, b) => b.day.compareTo(a.day)); return journal; } Future UpdateJournalsFromServer() async { Debug.Log("Updating Journal as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_journals.php'), body: {"username": username, "device_id": await Settings.UUID()})); Debug.LogResponse(response.body,src:'Journal'); List data = response.body.split(""); await cacheDb.delete("Journal"); for (var value in data) { Map 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("'", "''")}') "); } } catch (e) { Debug.LogError("Error while cats $e"); } } Future> GetTodos(bool forceOffline) async { if (cacheEnabled) { List _todos = []; if (offline || forceOffline) { //Retreive from cacheDB } else { //Check if server got updated, If not go for cache //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) { // Debug.Log(e); // } //Update CacheDB if (!catsUpdated) { await UpdateTodosFromServer(); } } List cats = await cacheDb.query('Todos'); Debug.Log(cats.length); for (Map element in cats) { String? id = element['id'].toString(); String? task_id = element[Todo.colCat]; String? metadata = element[Todo.colMetadata]; String? due_date = element[Todo.colDueDate]; String? notification_time = element[Todo.colNotificationTime]; if (id == null || task_id == null || metadata == null || due_date == null) { Debug.LogError("Something is null!"); Debug.LogError("id:{$id}, task:{$task_id}, metadata:${metadata}, due_date: ${due_date}"); continue; } TaskType? taskType = await getTaskFromId(task_id); if(taskType == null){Debug.LogError('got null taask for this todo!');Debug.LogResponse("id:{$id}, task:{$task_id}, metadata:${metadata}, due_date: ${due_date}");} DateTime dueDate = DateTime.parse(due_date); DateTime? notificationTime = (notification_time == null) ? null : ((notification_time.isEmpty || notification_time =='null') ? null :DateTime.parse(notification_time)); // Debug.Log("name:{$catName}, color:{$catColor}, prod:{$catProductive}"); _todos.add(Todo(id,task_id,metadata,dueDate, notificationTime: notificationTime, task:taskType)); } todos = _todos; } else { Debug.Log("NC: Updating todos as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_todos.php'), body: {"username": username, "device_id": await Settings.UUID()})); Debug.LogResponse(response.body); List data = response.body.split(""); List _categories = []; for (var value in data) { Map cat = jsonDecode(value); //Debug.Log(catData); _categories .add(Journal(cat['id'], DateTime.parse(cat['id'].toString().replaceAll(username, '')), title: cat['title'], description: cat['text'])); } journal = _categories; } catch (e) { Debug.LogError("Error while cats NC: $e"); } } // journal.sort((a, b) => b.day.compareTo(a.day)); return todos; } Future UpdateTodosFromServer() async { Debug.Log("Updating Todos as $username"); try { http.Response response = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/get_todos.php'), body: {"username": username, "device_id": await Settings.UUID()})); Debug.LogResponse(response.body); List data = response.body.split(""); await cacheDb.delete("Todos"); for (var value in data) { Map 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']}') "); } } catch (e) { Debug.LogError("Error while cats $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) { Debug.LogError('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; } Future getProjectFromId(String projectId) async { // await GetTaskTypes(false); Project? project = null; for (var element in projects) { if (element.getName() == projectId.replaceAll(username, "")) { project = element; } } if (project == null) { Debug.LogError('Got null project for ${projectId} after searching on ${projects.length}'); } return project; } bool journalExists(DateTime date){ int journalId = -1; for (int i =0; i < journal.length; i++) { // Debug.Log('${journal[i].day } : $date'); if(DateFormat('yyyy-MM-dd').format(journal[i].day) == DateFormat('yyyy-MM-dd').format(date)){ journalId = i; break; } } return (journalId > 0); } //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)}; Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('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, String? relatedProject = null}) async { Map queryBody = { 'id': username + name, 'username': username, 'device_id': await Settings.UUID(), 'name': name, 'category': username + category, 'related_project': (relatedProject == null) ? '' : (username + relatedProject) }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'add_taskType', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("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, }; if (relatedProject != null || relatedProject == 'None') { data.putIfAbsent(TaskType.colRelatedProject, () => relatedProject.toString()); } 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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error editing acti $e}'); } } if (!bulk) { //Add to server and refresh Cache await executeQueries(); } } static Future editTaskType(String oldName, String name, String category, {bool bulk = false, String? relatedProject = null}) async { Map queryBody = { 'id': username + oldName, 'username': username, 'name': name, 'category': username + category, 'related_project': (relatedProject == null) ? '' : (username + relatedProject) }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'edit_taskType', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); //update Cache await cacheDb.rawUpdate( "UPDATE TaskTypes SET ${TaskType.colId}='${username + name}', ${TaskType.colName}='$name', ${TaskType.colCategory}='${username + category}', ${TaskType.colRelatedProject}='${(relatedProject == 'None') ? '' : relatedProject}' WHERE id='${username + oldName}'"); 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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error editing task $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')))")); Debug.Log("ActivityOverlaps: $overlapCount"); if (overlapCount! > 0) { onOverlap!(overlapCount); return; } if (metadata.length > 0) {} //Add Query Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('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}')")); Debug.Log("ActivityOverlaps: $overlapCount"); if (overlapCount! > 0) { onOverlap!(overlapCount); return; } if (metadata.length > 0) {} //Add Query Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('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)}; Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('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)}; Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error adding ongoing $e}'); } } await executeQueries(); } static Future addProject(String name, String category, List steps, int eta, DateTime deadline) async { Map queryBody = { 'name': username + name, 'username': username, 'device_id': await Settings.UUID(), 'category_id': username + category, 'steps': jsonEncode(steps), 'eta': eta.toString(), 'deadline': DateFormat("yyyy-MM-dd").format(deadline) }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'add_project', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("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.colEta: eta, 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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error adding prjct $e}'); } } UserOperations.addTaskType(name, category, relatedProject: name); await executeQueries(); } static Future editProject(String oldName, String name, String category, List steps, int eta, DateTime deadline) async { Map queryBody = { 'oldName': username + oldName, 'name': username + name, 'username': username, 'category_id': username + category, 'steps': jsonEncode(steps), 'eta': eta.toString(), 'deadline': DateFormat("yyyy-MM-dd").format(deadline) }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'edit_project', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("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.colEta: eta, Project.colDeadline: deadline.toString() }; await cacheDb.rawUpdate( "UPDATE Projects SET ${Project.colName}='${username + name}', ${Project.colCat}='${username+category}', ${Project.colSteps}='${jsonEncode(steps)}', ${Project.colEta}='${eta}', ${Project.colDeadline}='${deadline.toString()}' WHERE ${Project.colName}='${username+oldName}'"); await cacheDb.rawUpdate("UPDATE TaskTypes SET ${TaskType.colRelatedProject}='${username+name}' WHERE ${TaskType.colRelatedProject}='${username+oldName}'"); await refreshUserData(forceOffline: true); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/edit_project.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error adding prjct $e}'); } } await executeQueries(); } static Future CompleteProjectStep(Project project, ProjectStep step, DateTime finishedDate) async { project.steps.forEach((element) { if (element.stepName == step.stepName) { element.finishedDate = finishedDate; } }); Map queryBody = { 'name': username + project.name, 'username': username, 'steps': jsonEncode(project.steps), }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'update_projectSteps', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); await cacheDb.rawUpdate("UPDATE Projects SET steps='${jsonEncode(project.steps)}' WHERE ${Project.colName}='${project.name}'"); //update Cache // Map data = {Project.colName: username+name, Project.colCat: category, Project.colSteps: jsonEncode(steps),Project.colEta: eta, 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/update_projectSteps.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error completing prjctStep $e}'); } } await executeQueries(); } static Future UndoProjectStep(Project project, ProjectStep step) async { project.steps.forEach((element) { if (element.stepName == step.stepName) { element.finishedDate = null; } }); Map queryBody = { 'name': username + project.name, 'username': username, 'steps': jsonEncode(project.steps), }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'update_projectSteps', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); await cacheDb.rawUpdate("UPDATE Projects SET steps='${jsonEncode(project.steps)}' WHERE ${Project.colName}='${project.name}'"); //update Cache // Map data = {Project.colName: username+name, Project.colCat: category, Project.colSteps: jsonEncode(steps),Project.colEta: eta, 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/update_projectSteps.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error completing prjctStep $e}'); } } await executeQueries(); } static Future addJournal(DateTime day, String title, String text) async { bool exist = false; for (var element in journal) { if (element.day == day) { //Wat! exist = true; break; } } if (exist) { return; } String id = username + DateFormat('yyyy-MM-dd').format(day); Map queryBody = {'username': username, 'id': id, 'title': title, 'description': text}; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'add_journal', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); //update Cache Map data = {'id': id, Journal.colTitle: title, Journal.colDescription: text}; await cacheDb.insert('Journal', data); await refreshUserData(forceOffline: true); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/add_journal.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error adding journal entry $e}'); } //executeQueries(); } //Add to server and refresh Cache await executeQueries(); } static Future editJournal(DateTime oldDay, DateTime day, String title, String text) async { String oldId = username + DateFormat('yyyy-MM-dd').format(oldDay); String id = username + DateFormat('yyyy-MM-dd').format(day); Map queryBody = {'username': username, 'old_id': oldId, 'id': id, 'title': title, 'description': text}; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'edit_journal', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); await cacheDb.rawUpdate( "UPDATE Journal SET id='$id', ${Journal.colTitle}='${title.toString().replaceAll("'", "''")}', ${Journal.colDescription}='${text.toString().replaceAll("'", "''")}' WHERE id='$oldId'"); //update Cache Map data = {'id': id, Journal.colTitle: title, Journal.colDescription: text}; // await cacheDb.insert('Journal', data); await refreshUserData(forceOffline: true); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/edit_journal.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error adding journal entry $e}'); } //executeQueries(); } //Add to server and refresh Cache await executeQueries(); } static Future addTodo(String taskType, String metadata, DateTime dueDate, DateTime? notificationTime) async { String taskId = username + taskType; if(taskId.contains('[') && taskId.contains(']')){ //has a project related taskId = taskId.substring(0, taskId.indexOf('[') - 1); } String id = taskId + metadata; Map queryBody = { 'username': username, 'task': taskId, 'metadata': metadata, 'due_date': DateFormat('yyyy-MM-dd').format(dueDate), if(notificationTime!=null)'notification_time':DateFormat('yyyy-MM-dd HH:mm').format(notificationTime) }; if (cacheEnabled) { //Add Query Map query = {Queries.colLink: 'add_todo', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); await cacheDb.insert('Queries', query); //update Cache Map data = {'id': id, Todo.colCat: taskId, Todo.colMetadata: metadata, Todo.colDueDate: DateFormat('yyyy-MM-dd').format(dueDate), if(notificationTime!=null)Todo.colNotificationTime:DateFormat('yyyy-MM-dd HH:mm').format(notificationTime)}; await cacheDb.insert('Todos', data); await refreshUserData(forceOffline: true); } else { try { http.Response queryResponse = (await http.post(Uri.parse('http://161.97.127.136/task_tracker/add_todo.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error adding journal entry $e}'); } //executeQueries(); } //Add to server and refresh Cache 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)}; Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('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)}; Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('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)}; Debug.LogResponse("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)}')"; Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error editing acti $e}'); } } if (!bulk) { await executeQueries(); } } static Future deleteProject(String project, {bulk = false}) async { Map queryBody = { 'username': username, 'name': username + project, }; //Add Query Map query = {Queries.colLink: 'delete_project', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); if (cacheEnabled) { await cacheDb.insert('Queries', query); //update Cache String deleteQuery = "DELETE FROM Projects WHERE ${Project.colName}='${username + project}'"; Debug.LogResponse("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_project.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error deleting project $e}'); } } if (!bulk) { await executeQueries(); } } static Future deleteJournal(String id, {bulk = false}) async { Map queryBody = { 'username': username, 'id': id, }; //Add Query Map query = {Queries.colLink: 'delete_journal', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); if (cacheEnabled) { await cacheDb.insert('Queries', query); //update Cache String deleteQuery = "DELETE FROM Journal WHERE id='$id'"; Debug.LogResponse("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_journal.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error deleting journal $e}'); } } if (!bulk) { await executeQueries(); } } static Future deleteTodo(String id, {bulk = false}) async { Map queryBody = { 'username': username, 'id': id, }; //Add Query Map query = {Queries.colLink: 'delete_todo', Queries.colData: jsonEncode(queryBody)}; Debug.LogResponse("adding new query ${query[Queries.colLink]} : ${jsonEncode(queryBody)}"); if (cacheEnabled) { await cacheDb.insert('Queries', query); //update Cache String deleteQuery = "DELETE FROM Todos WHERE id='$id'"; Debug.LogResponse("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_todo.php'), body: queryBody)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("success")) { //Success } } catch (e) { Debug.LogError('NC: Error deleting journal $e}'); } } if (!bulk) { await executeQueries(); } } static Future executeQueries() async { if (cacheEnabled) { if (offline) { Debug.Log("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) { Debug.LogError("Null query, Ignoring..."); continue; } Debug.LogResponse("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)); Debug.LogResponse("Query executed : Results{${queryResponse.body}"); if (queryResponse.body.toLowerCase().contains("+") || queryResponse.body.toLowerCase().contains("success")) { await cacheDb.rawDelete('DELETE FROM Queries WHERE id=$id'); } offline = false; } catch (e) { Debug.LogError("Error while query $e"); } } //await refreshUserData(); } else { await refreshUserData(); Debug.LogError('Trying to execute queries in no cahce mode, We dont do that here'); } } }