From 35d7b2a9f2b5fbc140e4693ef4b218abd9067a0a Mon Sep 17 00:00:00 2001 From: Shubham Ingale Date: Fri, 24 Jan 2025 18:47:17 +0530 Subject: [PATCH] feat: added websockets to receive job status --- .../home/controllers/home_controller.dart | 79 +++++++++++++++++-- lib/app/utils/taskchampion/websocket.dart | 40 ++++++++++ pubspec.yaml | 1 + 3 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 lib/app/utils/taskchampion/websocket.dart diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart index 53074874..ad9e0d4b 100644 --- a/lib/app/modules/home/controllers/home_controller.dart +++ b/lib/app/modules/home/controllers/home_controller.dart @@ -27,12 +27,15 @@ import 'package:taskwarrior/app/tour/home_page_tour.dart'; import 'package:taskwarrior/app/utils/constants/taskwarrior_colors.dart'; import 'package:taskwarrior/app/utils/language/supported_language.dart'; import 'package:taskwarrior/app/utils/taskchampion/credentials_storage.dart'; +import 'package:taskwarrior/app/utils/taskchampion/websocket.dart'; import 'package:taskwarrior/app/utils/taskfunctions/comparator.dart'; import 'package:taskwarrior/app/utils/taskfunctions/projects.dart'; import 'package:taskwarrior/app/utils/taskfunctions/query.dart'; import 'package:taskwarrior/app/utils/taskfunctions/tags.dart'; import 'package:taskwarrior/app/utils/app_settings/app_settings.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; +import 'package:web_socket_channel/status.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; class HomeController extends GetxController { final SplashController splashController = Get.find(); @@ -55,6 +58,7 @@ class HomeController extends GetxController { final ScrollController scrollController = ScrollController(); final RxBool showbtn = false.obs; late TaskDatabase taskdb; + WebSocketChannel? wsChannel; var tasks = [].obs; @override @@ -74,11 +78,18 @@ class HomeController extends GetxController { taskdb.open(); getUniqueProjects(); _loadTaskChampion(); + ever(taskchampion, (bool value) async { + if (value) { + wsChannel = await initCCSyncUpdatesWs(); + } else { + if (wsChannel != null) wsChannel?.sink.close(goingAway); + } + }); if (Platform.isAndroid) { handleHomeWidgetClicked(); } fetchTasksFromDB(); - everAll([ + everAll([ pendingFilter, waitingFilter, projectFilter, @@ -86,13 +97,13 @@ class HomeController extends GetxController { selectedSort, selectedTags, ], (_) { - if (Platform.isAndroid) { + if (Platform.isAndroid) { WidgetController widgetController = Get.put(WidgetController()); - widgetController.fetchAllData(); + widgetController.fetchAllData(); - widgetController.update(); - } + widgetController.update(); + } }); } @@ -518,7 +529,7 @@ class HomeController extends GetxController { ]; - RxString priority = 'X'.obs; + RxString priority = 'None'.obs; final tagcontroller = TextEditingController(); RxList tags = [].obs; @@ -717,4 +728,60 @@ class HomeController extends GetxController { Widget showDialog = taskchampion.value ? AddTaskToTaskcBottomSheet(homeController: this) : AddTaskBottomSheet(homeController: this); Get.dialog(showDialog); } + + Future initCCSyncUpdatesWs() async { + Map successMessages = { + "Add Task": "Task added successfully", + "Edit Task": "Task edited successfully", + "Complete Task": "Task completed successfully", + "Delete Task": "Task deleted successfully", + }; + Map failureMessages = { + "Add Task": "Task addition failed", + "Edit Task": "Task edit failed", + "Complete Task": "Task completion failed", + "Delete Task": "Task deletion failed", + }; + String? clientId = await CredentialsStorage.getClientId(); + return listenForTaskUpdates(getWsUrl(baseUrl, clientId), + (TaskUpdate update) { + debugPrint("Success: ${update.job} ${successMessages[update.job]!}"); + if (successMessages.containsKey(update.job)) { + ScaffoldMessenger.of(Get.context!).showSnackBar(SnackBar( + content: Text( + '${successMessages[update.job]}', + style: TextStyle( + color: AppSettings.isDarkMode + ? TaskWarriorColors.kprimaryTextColor + : TaskWarriorColors.kLightPrimaryTextColor, + ), + ), + backgroundColor: AppSettings.isDarkMode + ? TaskWarriorColors.ksecondaryBackgroundColor + : TaskWarriorColors.kLightSecondaryBackgroundColor, + duration: const Duration(seconds: 2))); + } + }, (TaskUpdate update) { + ScaffoldMessenger.of(Get.context!).showSnackBar(SnackBar( + content: Text( + '${failureMessages[update.job]}', + style: TextStyle( + color: AppSettings.isDarkMode + ? TaskWarriorColors.kprimaryTextColor + : TaskWarriorColors.kLightPrimaryTextColor, + ), + ), + backgroundColor: AppSettings.isDarkMode + ? TaskWarriorColors.ksecondaryBackgroundColor + : TaskWarriorColors.kLightSecondaryBackgroundColor, + duration: const Duration(seconds: 2))); + }); + } + + @override + void onClose() { + super.onClose(); + taskdb.close(); + if (wsChannel != null) wsChannel?.sink.close(); + } } diff --git a/lib/app/utils/taskchampion/websocket.dart b/lib/app/utils/taskchampion/websocket.dart new file mode 100644 index 00000000..90f14419 --- /dev/null +++ b/lib/app/utils/taskchampion/websocket.dart @@ -0,0 +1,40 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; + +class TaskUpdate { + final String status; + final String job; + const TaskUpdate(this.status, this.job); + TaskUpdate.fromJson(Map json) + : status = json['status'], + job = json['job']; + Map toJson() => { + 'status': status, + 'job': job, + }; +} + +Future listenForTaskUpdates(url, onSuccess, onFailure) async { + final webSocketChannel = WebSocketChannel.connect( + Uri.parse(url), + ); + await webSocketChannel.ready; + webSocketChannel.stream.listen((message) { + debugPrint(message); + TaskUpdate update = + TaskUpdate.fromJson(jsonDecode(message) as Map); + if (update.status == 'success') { + onSuccess(update); + } + if (update.status == 'failure') { + onFailure(update); + } + }); + return webSocketChannel; +} + +String getWsUrl(url, clientId) { + return url.replaceFirst('http', 'ws') + '/ws?clientID=' + clientId; +} diff --git a/pubspec.yaml b/pubspec.yaml index 19db109c..8204a524 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: url_launcher: ^6.1.14 uuid: ^4.2.2 built_collection: ^5.1.1 + web_socket_channel: ^2.4.0 dev_dependencies: build_runner: null