diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist
index 9625e10..7c56964 100644
--- a/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 11.0
+ 12.0
diff --git a/example/ios/Podfile b/example/ios/Podfile
index 88359b2..279576f 100644
--- a/example/ios/Podfile
+++ b/example/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
+# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
index c4f8411..c6464f7 100644
--- a/example/ios/Podfile.lock
+++ b/example/ios/Podfile.lock
@@ -1,28 +1,156 @@
PODS:
+ - DKImagePickerController/Core (4.3.9):
+ - DKImagePickerController/ImageDataManager
+ - DKImagePickerController/Resource
+ - DKImagePickerController/ImageDataManager (4.3.9)
+ - DKImagePickerController/PhotoGallery (4.3.9):
+ - DKImagePickerController/Core
+ - DKPhotoGallery
+ - DKImagePickerController/Resource (4.3.9)
+ - DKPhotoGallery (0.0.19):
+ - DKPhotoGallery/Core (= 0.0.19)
+ - DKPhotoGallery/Model (= 0.0.19)
+ - DKPhotoGallery/Preview (= 0.0.19)
+ - DKPhotoGallery/Resource (= 0.0.19)
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Core (0.0.19):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Preview
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Model (0.0.19):
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Preview (0.0.19):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Resource
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Resource (0.0.19):
+ - SDWebImage
+ - SwiftyGif
+ - file_picker (0.0.1):
+ - DKImagePickerController/PhotoGallery
+ - Flutter
- Flutter (1.0.0)
- - path_provider_ios (0.0.1):
+ - flutter_secure_storage (6.0.0):
+ - Flutter
+ - image_picker_ios (0.0.1):
+ - Flutter
+ - media_kit_libs_ios_video (1.0.4):
+ - Flutter
+ - media_kit_native_event_loop (1.0.0):
+ - Flutter
+ - media_kit_video (0.0.1):
+ - Flutter
+ - open_filex (0.0.2):
+ - Flutter
+ - package_info_plus (0.4.5):
- Flutter
+ - path_provider_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - screen_brightness_ios (0.1.0):
+ - Flutter
+ - SDWebImage (5.20.0):
+ - SDWebImage/Core (= 5.20.0)
+ - SDWebImage/Core (5.20.0)
+ - sqflite_darwin (0.0.4):
+ - Flutter
+ - FlutterMacOS
+ - SwiftyGif (5.4.5)
- url_launcher_ios (0.0.1):
- Flutter
+ - volume_controller (0.0.1):
+ - Flutter
+ - wakelock_plus (0.0.1):
+ - Flutter
+ - webview_flutter_wkwebview (0.0.1):
+ - Flutter
+ - FlutterMacOS
DEPENDENCIES:
+ - file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
- - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
+ - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
+ - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
+ - media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
+ - media_kit_native_event_loop (from `.symlinks/plugins/media_kit_native_event_loop/ios`)
+ - media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
+ - open_filex (from `.symlinks/plugins/open_filex/ios`)
+ - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
+ - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
+ - screen_brightness_ios (from `.symlinks/plugins/screen_brightness_ios/ios`)
+ - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+ - volume_controller (from `.symlinks/plugins/volume_controller/ios`)
+ - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
+ - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
+
+SPEC REPOS:
+ trunk:
+ - DKImagePickerController
+ - DKPhotoGallery
+ - SDWebImage
+ - SwiftyGif
EXTERNAL SOURCES:
+ file_picker:
+ :path: ".symlinks/plugins/file_picker/ios"
Flutter:
:path: Flutter
- path_provider_ios:
- :path: ".symlinks/plugins/path_provider_ios/ios"
+ flutter_secure_storage:
+ :path: ".symlinks/plugins/flutter_secure_storage/ios"
+ image_picker_ios:
+ :path: ".symlinks/plugins/image_picker_ios/ios"
+ media_kit_libs_ios_video:
+ :path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
+ media_kit_native_event_loop:
+ :path: ".symlinks/plugins/media_kit_native_event_loop/ios"
+ media_kit_video:
+ :path: ".symlinks/plugins/media_kit_video/ios"
+ open_filex:
+ :path: ".symlinks/plugins/open_filex/ios"
+ package_info_plus:
+ :path: ".symlinks/plugins/package_info_plus/ios"
+ path_provider_foundation:
+ :path: ".symlinks/plugins/path_provider_foundation/darwin"
+ screen_brightness_ios:
+ :path: ".symlinks/plugins/screen_brightness_ios/ios"
+ sqflite_darwin:
+ :path: ".symlinks/plugins/sqflite_darwin/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
+ volume_controller:
+ :path: ".symlinks/plugins/volume_controller/ios"
+ wakelock_plus:
+ :path: ".symlinks/plugins/wakelock_plus/ios"
+ webview_flutter_wkwebview:
+ :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
SPEC CHECKSUMS:
- Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
- path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
- url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2
+ DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
+ DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
+ file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
+ Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
+ flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
+ image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
+ media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1
+ media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a
+ media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
+ open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4
+ package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
+ path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
+ screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
+ SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8
+ sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
+ SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
+ url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
+ volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9
+ wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1
+ webview_flutter_wkwebview: 0982481e3d9c78fd5c6f62a002fcd24fc791f1e4
-PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
+PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011
-COCOAPODS: 1.11.3
+COCOAPODS: 1.15.2
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index 7979e62..c0f2cdd 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 50;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -156,7 +156,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1300;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -200,10 +200,12 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -231,6 +233,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -340,7 +343,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -414,7 +417,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -463,7 +466,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 3db53b6..e67b280 100644
--- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
CADisableMinimumFrameDurationOnPhone
+ UIApplicationSupportsIndirectInputEvents
+
diff --git a/example/lib/main.dart b/example/lib/main.dart
index cb0ff98..ca6a576 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -46,33 +46,15 @@ class _MyHomePageState extends State {
appBar: AppBar(
title: Text("Chatwoot Example"),
),
- body: ChatwootWidget(
- websiteToken: "websiteToken",
- baseUrl: "https://app.chatwoot.com",
+ body: ChatwootChat(
+ baseUrl: "https://chat.goldenprizma.com",
user: ChatwootUser(
identifier: "test@test.com",
name: "Tester test",
email: "test@test.com",
),
- locale: "en",
- closeWidget: () {
- if (Platform.isAndroid) {
- SystemNavigator.pop();
- } else if (Platform.isIOS) {
- exit(0);
- }
- },
- //attachment only works on android for now
- onAttachFile: _androidFilePicker,
- onLoadStarted: () {
- print("loading widget");
- },
- onLoadProgress: (int progress) {
- print("loading... ${progress}");
- },
- onLoadCompleted: () {
- print("widget loaded");
- },
+ //attachment only works on android for now,
+ inboxIdentifier: 'gHgywYWNz6nbrNp2GzWBvaYo',
),
);
}
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 3b17edf..97363e8 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -37,26 +37,26 @@ packages:
dependency: transitive
description:
name: cached_network_image
- sha256: "4a5d8d2c728b0f3d0245f69f921d7be90cae4c2fd5288f773088672c0893f819"
+ sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f"
url: "https://pub.dev"
source: hosted
- version: "3.4.0"
+ version: "3.3.1"
cached_network_image_platform_interface:
dependency: transitive
description:
name: cached_network_image_platform_interface
- sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
+ sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f"
url: "https://pub.dev"
source: hosted
- version: "4.1.1"
+ version: "4.0.0"
cached_network_image_web:
dependency: transitive
description:
name: cached_network_image_web
- sha256: "6322dde7a5ad92202e64df659241104a43db20ed594c41ca18de1014598d7996"
+ sha256: "205d6a9f1862de34b93184f22b9d2d94586b2f05c581d546695e3d8f6a805cd7"
url: "https://pub.dev"
source: hosted
- version: "1.3.0"
+ version: "1.2.0"
characters:
dependency: transitive
description:
@@ -140,18 +140,10 @@ packages:
dependency: transitive
description:
name: dio
- sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260"
+ sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8"
url: "https://pub.dev"
source: hosted
- version: "5.7.0"
- dio_web_adapter:
- dependency: transitive
- description:
- name: dio_web_adapter
- sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8"
- url: "https://pub.dev"
- source: hosted
- version: "2.0.0"
+ version: "4.0.6"
easy_image_viewer:
dependency: transitive
description:
@@ -232,14 +224,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.9.3+3"
- fixnum:
- dependency: transitive
- description:
- name: fixnum
- sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
- url: "https://pub.dev"
- source: hosted
- version: "1.1.1"
flutter:
dependency: "direct main"
description: flutter
@@ -249,10 +233,10 @@ packages:
dependency: transitive
description:
name: flutter_cache_manager
- sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
+ sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
url: "https://pub.dev"
source: hosted
- version: "3.4.1"
+ version: "3.3.1"
flutter_chat_types:
dependency: transitive
description:
@@ -289,10 +273,10 @@ packages:
dependency: transitive
description:
name: flutter_markdown
- sha256: "999a4e3cb3e1532a971c86d6c73a480264f6a687959d4887cb4e2990821827e4"
+ sha256: "255b00afa1a7bad19727da6a7780cf3db6c3c12e68d302d85e0ff1fdf173db9e"
url: "https://pub.dev"
source: hosted
- version: "0.7.4+2"
+ version: "0.7.4+3"
flutter_parsed_text:
dependency: transitive
description:
@@ -313,10 +297,10 @@ packages:
dependency: transitive
description:
name: flutter_secure_storage
- sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0"
+ sha256: "22dbf16f23a4bcf9d35e51be1c84ad5bb6f627750565edd70dab70f3ff5fff8f"
url: "https://pub.dev"
source: hosted
- version: "9.2.2"
+ version: "8.1.0"
flutter_secure_storage_linux:
dependency: transitive
description:
@@ -353,10 +337,10 @@ packages:
dependency: transitive
description:
name: flutter_secure_storage_windows
- sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
+ sha256: "38f9501c7cb6f38961ef0e1eacacee2b2d4715c63cc83fe56449c4d3d0b47255"
url: "https://pub.dev"
source: hosted
- version: "3.1.2"
+ version: "2.1.1"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -367,6 +351,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ freezed_annotation:
+ dependency: transitive
+ description:
+ name: freezed_annotation
+ sha256: "70776c4541e5cacfe45bcaf00fe79137b8c61aa34fb5765a05ce6c57fd72c6e9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.14.3"
hive:
dependency: transitive
description:
@@ -395,10 +387,10 @@ packages:
dependency: transitive
description:
name: http
- sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
+ sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
url: "https://pub.dev"
source: hosted
- version: "1.2.2"
+ version: "0.13.6"
http_parser:
dependency: transitive
description:
@@ -483,10 +475,10 @@ packages:
dependency: transitive
description:
name: intl
- sha256: "99f282cb0e02edcbbf8c6b3bbc7c90b65635156c412e58f3975a7e55284ce685"
+ sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
url: "https://pub.dev"
source: hosted
- version: "0.20.0"
+ version: "0.17.0"
js:
dependency: transitive
description:
@@ -771,18 +763,18 @@ packages:
dependency: transitive
description:
name: riverpod
- sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959"
+ sha256: "13cbe0e17b659f38027986df967b3eaf7f42c519786352167fc3db1be44eae07"
url: "https://pub.dev"
source: hosted
- version: "2.6.1"
+ version: "0.14.0+3"
rxdart:
dependency: transitive
description:
name: rxdart
- sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
+ sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
url: "https://pub.dev"
source: hosted
- version: "0.28.0"
+ version: "0.27.7"
safe_local_storage:
dependency: transitive
description:
@@ -860,14 +852,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.0"
- sprintf:
- dependency: transitive
- description:
- name: sprintf
- sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
- url: "https://pub.dev"
- source: hosted
- version: "7.0.0"
sqflite:
dependency: transitive
description:
@@ -920,10 +904,10 @@ packages:
dependency: transitive
description:
name: state_notifier
- sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
+ sha256: "8fe42610f179b843b12371e40db58c9444f8757f8b69d181c97e50787caed289"
url: "https://pub.dev"
source: hosted
- version: "1.0.0"
+ version: "0.7.2+1"
stream_channel:
dependency: transitive
description:
@@ -1056,10 +1040,10 @@ packages:
dependency: transitive
description:
name: uuid
- sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
+ sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
url: "https://pub.dev"
source: hosted
- version: "4.5.1"
+ version: "3.0.7"
vector_math:
dependency: transitive
description:
@@ -1116,22 +1100,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.5.1"
- web_socket:
- dependency: transitive
- description:
- name: web_socket
- sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
- url: "https://pub.dev"
- source: hosted
- version: "0.1.6"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
- sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
+ sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
url: "https://pub.dev"
source: hosted
- version: "3.0.1"
+ version: "2.4.5"
webview_flutter:
dependency: transitive
description:
@@ -1189,5 +1165,5 @@ packages:
source: hosted
version: "6.5.0"
sdks:
- dart: ">=3.5.3 <4.0.0"
+ dart: ">=3.5.2 <4.0.0"
flutter: ">=3.24.0"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index f6b0b41..890761c 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
- sdk: "^3.5.3"
+ sdk: "^3.5.2"
dependencies:
flutter:
diff --git a/lib/data/remote/service/chatwoot_client_auth_service.dart b/lib/data/remote/service/chatwoot_client_auth_service.dart
index 438c3bb..e809b5c 100644
--- a/lib/data/remote/service/chatwoot_client_auth_service.dart
+++ b/lib/data/remote/service/chatwoot_client_auth_service.dart
@@ -44,9 +44,9 @@ class ChatwootClientAuthServiceImpl extends ChatwootClientAuthService {
createResponse.statusMessage ?? "unknown error",
ChatwootClientExceptionType.CREATE_CONTACT_FAILED);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.CREATE_CONTACT_FAILED);
+ e.message, ChatwootClientExceptionType.CREATE_CONTACT_FAILED);
}
}
@@ -67,9 +67,9 @@ class ChatwootClientAuthServiceImpl extends ChatwootClientAuthService {
createResponse.statusMessage ?? "unknown error",
ChatwootClientExceptionType.CREATE_CONVERSATION_FAILED);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.CREATE_CONVERSATION_FAILED);
+ e.message, ChatwootClientExceptionType.CREATE_CONVERSATION_FAILED);
}
}
}
diff --git a/lib/data/remote/service/chatwoot_client_service.dart b/lib/data/remote/service/chatwoot_client_service.dart
index 0032b90..aca9eaf 100644
--- a/lib/data/remote/service/chatwoot_client_service.dart
+++ b/lib/data/remote/service/chatwoot_client_service.dart
@@ -14,7 +14,7 @@ import 'package:chatwoot_sdk/data/remote/service/chatwoot_client_api_interceptor
import 'package:dio/dio.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:mime/mime.dart';
-
+import 'package:http_parser/http_parser.dart';
/// Service for handling chatwoot api calls
/// See [ChatwootClientServiceImpl]
@@ -36,7 +36,8 @@ abstract class ChatwootClientService {
Future updateMessage(String messageIdentifier, update);
- Future sendCsatFeedBack(String conversationUuid, SendCsatSurveyRequest request);
+ Future sendCsatFeedBack(
+ String conversationUuid, SendCsatSurveyRequest request);
Future getCsatFeedback(String conversationUuid);
@@ -49,7 +50,8 @@ abstract class ChatwootClientService {
}
class ChatwootClientServiceImpl extends ChatwootClientService {
- ChatwootClientServiceImpl(String baseUrl, {required Dio dio, required Dio uDio})
+ ChatwootClientServiceImpl(String baseUrl,
+ {required Dio dio, required Dio uDio})
: super(baseUrl, dio, uDio);
///Sends message to chatwoot inbox
@@ -57,17 +59,19 @@ class ChatwootClientServiceImpl extends ChatwootClientService {
Future createMessage(
ChatwootNewMessageRequest request) async {
try {
-
FormData formData = FormData.fromMap({
'echo_id': request.echoId,
'content': request.content,
});
- for(final attachment in request.attachments){
- formData.files.add(MapEntry('attachments[]',await MultipartFile.fromBytes(
- attachment.bytes,
- filename: attachment.name,
- contentType: DioMediaType.parse(lookupMimeType(attachment.name) ?? 'application/octet-stream')
- )));
+ for (final attachment in request.attachments) {
+ formData.files.add(MapEntry(
+ 'attachments[]',
+ await MultipartFile.fromBytes(
+ attachment.bytes,
+ filename: attachment.name,
+ contentType: MediaType.parse(lookupMimeType(attachment.name) ??
+ 'application/octet-stream'),
+ )));
}
final createResponse = await _dio.post(
"/public/api/v1/inboxes/${ChatwootClientApiInterceptor.INTERCEPTOR_INBOX_IDENTIFIER_PLACEHOLDER}/contacts/${ChatwootClientApiInterceptor.INTERCEPTOR_CONTACT_IDENTIFIER_PLACEHOLDER}/conversations/${ChatwootClientApiInterceptor.INTERCEPTOR_CONVERSATION_IDENTIFIER_PLACEHOLDER}/messages",
@@ -81,9 +85,9 @@ class ChatwootClientServiceImpl extends ChatwootClientService {
createResponse.statusMessage ?? "unknown error",
ChatwootClientExceptionType.SEND_MESSAGE_FAILED);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.SEND_MESSAGE_FAILED);
+ e.message, ChatwootClientExceptionType.SEND_MESSAGE_FAILED);
}
}
@@ -103,9 +107,9 @@ class ChatwootClientServiceImpl extends ChatwootClientService {
createResponse.statusMessage ?? "unknown error",
ChatwootClientExceptionType.GET_MESSAGES_FAILED);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.GET_MESSAGES_FAILED);
+ e.message, ChatwootClientExceptionType.GET_MESSAGES_FAILED);
}
}
@@ -122,9 +126,9 @@ class ChatwootClientServiceImpl extends ChatwootClientService {
getResponse.statusMessage ?? "unknown error",
ChatwootClientExceptionType.GET_CONTACT_FAILED);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.GET_CONTACT_FAILED);
+ e.message, ChatwootClientExceptionType.GET_CONTACT_FAILED);
}
}
@@ -143,9 +147,9 @@ class ChatwootClientServiceImpl extends ChatwootClientService {
createResponse.statusMessage ?? "unknown error",
ChatwootClientExceptionType.GET_CONVERSATION_FAILED);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.GET_CONVERSATION_FAILED);
+ e.message, ChatwootClientExceptionType.GET_CONVERSATION_FAILED);
}
}
@@ -163,9 +167,9 @@ class ChatwootClientServiceImpl extends ChatwootClientService {
updateResponse.statusMessage ?? "unknown error",
ChatwootClientExceptionType.UPDATE_CONTACT_FAILED);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.UPDATE_CONTACT_FAILED);
+ e.message, ChatwootClientExceptionType.UPDATE_CONTACT_FAILED);
}
}
@@ -185,9 +189,9 @@ class ChatwootClientServiceImpl extends ChatwootClientService {
updateResponse.statusMessage ?? "unknown error",
ChatwootClientExceptionType.UPDATE_MESSAGE_FAILED);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.UPDATE_MESSAGE_FAILED);
+ e.message, ChatwootClientExceptionType.UPDATE_MESSAGE_FAILED);
}
}
@@ -225,45 +229,44 @@ class ChatwootClientServiceImpl extends ChatwootClientService {
}
@override
- Future getCsatFeedback(String conversationUuid) async{
+ Future getCsatFeedback(
+ String conversationUuid) async {
try {
- final response = await _dio.get(
- "/public/api/v1/csat_survey/$conversationUuid");
+ final response =
+ await _dio.get("/public/api/v1/csat_survey/$conversationUuid");
if ((response.statusCode ?? 0).isBetween(199, 300)) {
- return response.data != null ? CsatSurveyFeedbackResponse.fromJson(response.data) : null;
+ return response.data != null
+ ? CsatSurveyFeedbackResponse.fromJson(response.data)
+ : null;
} else {
- throw ChatwootClientException(
- response.statusMessage ?? "unknown error",
+ throw ChatwootClientException(response.statusMessage ?? "unknown error",
ChatwootClientExceptionType.GET_CSAT_FEEDBACK);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.GET_CSAT_FEEDBACK);
+ e.message, ChatwootClientExceptionType.GET_CSAT_FEEDBACK);
}
}
@override
- Future sendCsatFeedBack(String conversationUuid, SendCsatSurveyRequest request) async{
+ Future sendCsatFeedBack(
+ String conversationUuid, SendCsatSurveyRequest request) async {
try {
- final response = await _udio.put(
- "/public/api/v1/csat_survey/$conversationUuid",
- data: {
- "message":{
- "submitted_values":{
- "csat_survey_response": request.toJson()
- }
- }
- });
+ final response = await _udio
+ .put("/public/api/v1/csat_survey/$conversationUuid", data: {
+ "message": {
+ "submitted_values": {"csat_survey_response": request.toJson()}
+ }
+ });
if ((response.statusCode ?? 0).isBetween(199, 300)) {
return CsatSurveyFeedbackResponse.fromJson(response.data);
} else {
- throw ChatwootClientException(
- response.statusMessage ?? "unknown error",
+ throw ChatwootClientException(response.statusMessage ?? "unknown error",
ChatwootClientExceptionType.SEND_CSAT_FEEDBACK);
}
- } on DioException catch (e) {
+ } on DioError catch (e) {
throw ChatwootClientException(
- e.message ?? '', ChatwootClientExceptionType.SEND_CSAT_FEEDBACK);
+ e.message, ChatwootClientExceptionType.SEND_CSAT_FEEDBACK);
}
}
}
diff --git a/lib/ui/chatwoot_chat_page.dart b/lib/ui/chatwoot_chat_page.dart
index 10a1cad..ab694a6 100644
--- a/lib/ui/chatwoot_chat_page.dart
+++ b/lib/ui/chatwoot_chat_page.dart
@@ -26,8 +26,7 @@ import 'package:path_provider/path_provider.dart';
import 'package:uuid/uuid.dart';
import 'package:http/http.dart' as http;
-
-class FileAttachment{
+class FileAttachment {
final Uint8List bytes;
final String name;
final String path;
@@ -35,7 +34,6 @@ class FileAttachment{
FileAttachment({required this.bytes, required this.name, required this.path});
}
-
///Chatwoot chat widget
/// {@category FlutterClientSdk}
class ChatwootChat extends StatefulWidget {
@@ -50,7 +48,6 @@ class ChatwootChat extends StatefulWidget {
/// For more details see https://www.chatwoot.com/docs/product/channels/api/client-apis
final String inboxIdentifier;
-
///Key used to generate user identifier hash
///
/// For more details see https://www.chatwoot.com/docs/product/channels/api/client-apis
@@ -181,7 +178,8 @@ class ChatwootChat extends StatefulWidget {
_ChatwootChatState createState() => _ChatwootChatState();
}
-class _ChatwootChatState extends State with WidgetsBindingObserver{
+class _ChatwootChatState extends State
+ with WidgetsBindingObserver {
///
List _messages = [];
@@ -222,10 +220,10 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
onConfirmedSubscription: () {
widget.onConfirmedSubscription?.call();
},
- onConversationIsOnline: (){
+ onConversationIsOnline: () {
widget.onConversationIsOnline?.call();
},
- onConversationIsOffline: (){
+ onConversationIsOffline: () {
widget.onConversationIsOffline?.call();
},
onConversationStartedTyping: () {
@@ -238,7 +236,7 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
if (widget.enablePersistence) {
setState(() {
_messages = persistedMessages
- .where((m)=>m.contentType != "input_csat")
+ .where((m) => m.contentType != "input_csat")
.map((message) => _chatwootMessageToTextMessage(message))
.toList();
});
@@ -251,16 +249,15 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
}
setState(() {
final chatMessages = messages
- .where((m)=>m.contentType != "input_csat")
- .map((message){
- return _chatwootMessageToTextMessage(message);
- })
- .toList();
+ .where((m) => m.contentType != "input_csat")
+ .map((message) {
+ return _chatwootMessageToTextMessage(message);
+ }).toList();
final mergedMessages = mergeLists(
- list1: chatMessages, list2: _messages,
- getItemKey: (item)=>item.id,
- merger: (item1, item2)=>item1
- );
+ list1: chatMessages,
+ list2: _messages,
+ getItemKey: (item) => item.id,
+ merger: (item1, item2) => item1);
final now = DateTime.now().millisecondsSinceEpoch;
mergedMessages.sort((a, b) {
return (b.createdAt ?? now).compareTo(a.createdAt ?? now);
@@ -270,7 +267,7 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
widget.onMessagesRetrieved?.call(messages);
},
onMessageReceived: (chatwootMessage) {
- if(chatwootMessage.contentType == "input_csat"){
+ if (chatwootMessage.contentType == "input_csat") {
//csat message is handled manually
return;
}
@@ -286,38 +283,36 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
widget.onMessageUpdated?.call(chatwootMessage);
},
onMessageSent: (chatwootMessage, echoId) {
- types.Message textMessage = _chatwootMessageToTextMessage(chatwootMessage, echoId: echoId, messageStatus: types.Status.sent);
+ types.Message textMessage = _chatwootMessageToTextMessage(
+ chatwootMessage,
+ echoId: echoId,
+ messageStatus: types.Status.sent);
_handleMessageSent(textMessage);
widget.onMessageSent?.call(chatwootMessage);
},
onConversationResolved: (conversationUuid) {
-
final resolvedMessage = types.TextMessage(
id: "resolved",
text: widget.l10n.conversationResolvedMessage,
author: types.User(
- id: idGen.v4(),),
+ id: idGen.v4(),
+ ),
status: types.Status.delivered);
_addMessage(resolvedMessage);
final csatMessage = types.CustomMessage(
id: "csat",
author: types.User(
- id: idGen.v4(),),
- metadata: {
- "conversationUuid": conversationUuid
- },
+ id: idGen.v4(),
+ ),
+ metadata: {"conversationUuid": conversationUuid},
status: types.Status.delivered);
_addMessage(csatMessage);
},
- onCsatSurveyResponseRecorded: (feedback){
-
+ onCsatSurveyResponseRecorded: (feedback) {
final resolvedMessage = types.CustomMessage(
id: "csat",
- author: types.User(
- id: idGen.v4()),
- metadata: {
- "feedback": feedback
- },
+ author: types.User(id: idGen.v4()),
+ metadata: {"feedback": feedback},
status: types.Status.delivered);
_handleMessageUpdated(resolvedMessage);
},
@@ -381,8 +376,8 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
return result;
}
-
- types.Message _chatwootMessageToTextMessage(ChatwootMessage message, {String? echoId, types.Status? messageStatus}) {
+ types.Message _chatwootMessageToTextMessage(ChatwootMessage message,
+ {String? echoId, types.Status? messageStatus}) {
String? avatarUrl = message.sender?.avatarUrl ?? message.sender?.thumbnail;
//Sets avatar url to null if its a gravatar not found url
@@ -390,28 +385,28 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
if (avatarUrl?.contains("?d=404") ?? false) {
avatarUrl = null;
}
- final nameSplit = (message.sender?.name??"C ").split(" ");
+ final nameSplit = (message.sender?.name ?? "C ").split(" ");
final firstName = nameSplit.first;
final lastName = nameSplit.last;
types.User author = message.isMine
? _user
: types.User(
- id: message.sender?.id.toString() ?? idGen.v4(),
- firstName: firstName,
- lastName: lastName,
- imageUrl: avatarUrl,
- );
+ id: message.sender?.id.toString() ?? idGen.v4(),
+ firstName: firstName,
+ lastName: lastName,
+ imageUrl: avatarUrl,
+ );
final metadata = {
- "sentAt": DateFormat("MMM d, hh:mm a").format(DateTime.parse(message.createdAt))
+ "sentAt":
+ DateFormat("MMM d, hh:mm a").format(DateTime.parse(message.createdAt))
};
- if(message.attachments?.first.dataUrl?.isNotEmpty ?? false){
+ if (message.attachments?.first.dataUrl?.isNotEmpty ?? false) {
Uri uri = Uri.parse(message.attachments!.first.dataUrl!);
// Get the last path segment from the URL (after the last '/')
- String fileName = uri.pathSegments.isNotEmpty
- ? uri.pathSegments.last
- : '';
- if(message.attachments!.first.fileType == "image"){
+ String fileName =
+ uri.pathSegments.isNotEmpty ? uri.pathSegments.last : '';
+ if (message.attachments!.first.fileType == "image") {
return types.ImageMessage(
id: echoId ?? message.id.toString(),
author: author,
@@ -420,8 +415,9 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
size: message.attachments!.first.fileSize ?? 0,
uri: message.attachments!.first.dataUrl!,
status: messageStatus ?? types.Status.seen,
- createdAt: DateTime.parse(message.createdAt).millisecondsSinceEpoch);
- }else if(message.attachments!.first.fileType == "video"){
+ createdAt:
+ DateTime.parse(message.createdAt).millisecondsSinceEpoch);
+ } else if (message.attachments!.first.fileType == "video") {
final videoMessage = types.VideoMessage(
id: echoId ?? message.id.toString(),
author: author,
@@ -432,22 +428,25 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
size: message.attachments!.first.fileSize ?? 0,
uri: message.attachments!.first.dataUrl!,
status: messageStatus ?? types.Status.seen,
- createdAt: DateTime.parse(message.createdAt).millisecondsSinceEpoch);
+ createdAt:
+ DateTime.parse(message.createdAt).millisecondsSinceEpoch);
- videoPreviewLoader.getPreview(jobId: videoMessage.id, uri: videoMessage.uri);
+ videoPreviewLoader.getPreview(
+ jobId: videoMessage.id, uri: videoMessage.uri);
return videoMessage;
- }else if(message.attachments!.first.fileType == "audio"){
+ } else if (message.attachments!.first.fileType == "audio") {
return types.AudioMessage(
id: echoId ?? message.id.toString(),
author: author,
- duration:Duration.zero,
+ duration: Duration.zero,
name: fileName,
metadata: metadata,
size: message.attachments!.first.fileSize ?? 0,
uri: message.attachments!.first.dataUrl!,
status: messageStatus ?? types.Status.seen,
- createdAt: DateTime.parse(message.createdAt).millisecondsSinceEpoch);
- }else{
+ createdAt:
+ DateTime.parse(message.createdAt).millisecondsSinceEpoch);
+ } else {
return types.FileMessage(
id: echoId ?? message.id.toString(),
author: author,
@@ -456,7 +455,8 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
size: message.attachments!.first.fileSize ?? 0,
uri: message.attachments!.first.dataUrl!,
status: messageStatus ?? types.Status.seen,
- createdAt: DateTime.parse(message.createdAt).millisecondsSinceEpoch);
+ createdAt:
+ DateTime.parse(message.createdAt).millisecondsSinceEpoch);
}
}
@@ -506,9 +506,7 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
});
}
-
void _handleMessageTap(BuildContext _, types.Message message) async {
-
if (message.status == types.Status.error && message is types.TextMessage) {
_handleResendMessage(message);
return;
@@ -517,33 +515,29 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
var localPath = message.uri;
if (localPath.startsWith('http')) {
-
- final documentsDir = (await getApplicationDocumentsDirectory()).path;
- final cacheLocalPath = '$documentsDir/${message.name}';
-
- if (!File(cacheLocalPath).existsSync()) {
-
- final client = http.Client();
- final request = await client.get(Uri.parse(localPath));
- final bytes = request.bodyBytes;
- final file = File(cacheLocalPath);
- await file.writeAsBytes(bytes);
- }
- localPath = cacheLocalPath;
-
+ final documentsDir = (await getApplicationDocumentsDirectory()).path;
+ final cacheLocalPath = '$documentsDir/${message.name}';
+
+ if (!File(cacheLocalPath).existsSync()) {
+ final client = http.Client();
+ final request = await client.get(Uri.parse(localPath));
+ final bytes = request.bodyBytes;
+ final file = File(cacheLocalPath);
+ await file.writeAsBytes(bytes);
+ }
+ localPath = cacheLocalPath;
}
widget.onMessageTap?.call(context, message);
await widget.openFile?.call(localPath);
}
- if(message is types.ImageMessage){
+ if (message is types.ImageMessage) {
final imageProvider = CachedNetworkImageProvider(message.uri);
showImageViewer(context, imageProvider);
}
}
-
void _handleMessageSent(
types.Message message,
) {
@@ -557,10 +551,10 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
}
void _handleMessageUpdated(
- types.Message message,
- ) {
+ types.Message message,
+ ) {
final index = _messages.indexWhere((element) => element.id == message.id);
- if(index == -1){
+ if (index == -1) {
return;
}
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -570,17 +564,13 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
});
}
- void _handleVideoPreviewLoaded(
- VideoMessagePreviewResult result
- ) {
-
+ void _handleVideoPreviewLoaded(VideoMessagePreviewResult result) {
final index = _messages.indexWhere((element) => element.id == result.jobId);
- if(index > -1){
+ if (index > -1) {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
- _messages[index] = _messages[index].copyWith(metadata: {
- "preview": result.preview
- });
+ _messages[index] =
+ _messages[index].copyWith(metadata: {"preview": result.preview});
});
});
}
@@ -601,11 +591,11 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
widget.onSendPressed?.call(message);
}
- void _handleAttachmentPressed() async{
+ void _handleAttachmentPressed() async {
final attachment = await widget.onAttachmentPressed?.call();
- if(attachment != null){
+ if (attachment != null) {
types.Message message;
- if(lookupMimeType(attachment.name)?.startsWith("image") ?? false){
+ if (lookupMimeType(attachment.name)?.startsWith("image") ?? false) {
message = types.ImageMessage(
author: _user,
createdAt: DateTime.now().millisecondsSinceEpoch,
@@ -614,8 +604,8 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
uri: attachment.path,
size: attachment.bytes.length,
status: types.Status.sending);
- }else if(lookupMimeType(attachment.name)?.startsWith("video") ?? false){
-
+ } else if (lookupMimeType(attachment.name)?.startsWith("video") ??
+ false) {
message = types.VideoMessage(
author: _user,
createdAt: DateTime.now().millisecondsSinceEpoch,
@@ -626,7 +616,8 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
status: types.Status.sending);
videoPreviewLoader.getPreview(jobId: message.id, uri: attachment.path);
- }else if(lookupMimeType(attachment.name)?.startsWith("audio") ?? false){
+ } else if (lookupMimeType(attachment.name)?.startsWith("audio") ??
+ false) {
message = types.AudioMessage(
author: _user,
createdAt: DateTime.now().millisecondsSinceEpoch,
@@ -636,7 +627,7 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
size: attachment.bytes.length,
duration: Duration.zero,
status: types.Status.sending);
- }else{
+ } else {
message = types.FileMessage(
author: _user,
createdAt: DateTime.now().millisecondsSinceEpoch,
@@ -649,12 +640,13 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
_addMessage(message);
- chatwootClient!
- .sendMessage(content: attachment.name, echoId: message.id, attachment: [attachment]);
+ chatwootClient!.sendMessage(
+ content: attachment.name,
+ echoId: message.id,
+ attachment: [attachment]);
}
}
-
@override
Widget build(BuildContext context) {
final horizontalPadding = widget.isPresentedInDialog ? 8.0 : 16.0;
@@ -666,7 +658,13 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
children: [
//offscreen video player used to fetch first frame of video messages. media_kit screenshot doesn't work without
//controller tied to the video widget
- IgnorePointer(child:Opacity(opacity: 0,child: Video(controller: controller, fit: BoxFit.contain,))),
+ IgnorePointer(
+ child: Opacity(
+ opacity: 0,
+ child: Video(
+ controller: controller,
+ fit: BoxFit.contain,
+ ))),
//actual chat
Column(
children: [
@@ -677,18 +675,18 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
child: Chat(
messages: _messages,
onMessageTap: _handleMessageTap,
- onPreviewDataFetched: (_,__){},
- onSendPressed: (_){},
+ onPreviewDataFetched: (_, __) {},
+ onSendPressed: (_) {},
user: _user,
onEndReached: widget.onEndReached,
onEndReachedThreshold: widget.onEndReachedThreshold,
onMessageLongPress: widget.onMessageLongPress,
- onAttachmentPressed: (){},
+ onAttachmentPressed: () {},
showUserAvatars: widget.showUserAvatars,
showUserNames: widget.showUserNames,
theme: theme,
disableImageGallery: true,
- dateHeaderBuilder: (_){
+ dateHeaderBuilder: (_) {
return SizedBox();
},
customBottomWidget: ChatInput(
@@ -696,98 +694,90 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
l10n: widget.l10n,
onMessageSent: _handleSendPressed,
onAttachmentPressed: _handleAttachmentPressed),
- textMessageBuilder: (message, {messageWidth=0, showName=true}){
+ textMessageBuilder: (message,
+ {messageWidth = 0, showName = true}) {
return TextChatMessage(
theme: theme,
message: message,
isMine: message.author.id == _user.id,
maxWidth: messageWidth,
- onPreviewFetched: _handlePreviewDataFetched
- );
+ onPreviewFetched: _handlePreviewDataFetched);
},
- videoMessageBuilder: (message, {messageWidth=0}){
+ videoMessageBuilder: (message, {messageWidth = 0}) {
return VideoChatMessage(
theme: theme,
message: message,
isMine: message.author.id == _user.id,
- maxWidth: messageWidth
- );
+ maxWidth: messageWidth);
},
- audioMessageBuilder: (message, {messageWidth=0}){
+ audioMessageBuilder: (message, {messageWidth = 0}) {
return AudioChatMessage(
- theme: theme,
- message: message,
- isMine: message.author.id == _user.id,
+ theme: theme,
+ message: message,
+ isMine: message.author.id == _user.id,
);
},
- avatarBuilder: (user){
+ avatarBuilder: (user) {
return Row(
children: [
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15)),
child: CachedNetworkImage(
- imageUrl: user.imageUrl ?? '',
- width: 30,
- height: 30,
- fit:BoxFit.cover,
- errorWidget: (_,__, ___){
- String name = "${user.firstName} ${user.lastName}";
- List words = name.trim().split(RegExp(r'\s+'));
- String initials = words.map((word) => word[0].toUpperCase()).join();
- return PlaceholderCircle(
- text: initials,
- textColor: theme.primaryColor,
- );
- },
+ imageUrl: user.imageUrl ?? '',
+ width: 30,
+ height: 30,
+ fit: BoxFit.cover,
+ errorWidget: (_, __, ___) {
+ String name =
+ "${user.firstName} ${user.lastName}";
+ List words =
+ name.trim().split(RegExp(r'\s+'));
+ String initials = words
+ .map((word) => word[0].toUpperCase())
+ .join();
+ return PlaceholderCircle(
+ text: initials,
+ textColor: theme.primaryColor,
+ );
+ },
),
),
- SizedBox(width: 5,)
+ SizedBox(
+ width: 5,
+ )
],
);
},
- customMessageBuilder: (message, {messageWidth=0}){
- if(message.metadata?["feedback"] != null){
+ customMessageBuilder: (message, {messageWidth = 0}) {
+ if (message.metadata?["feedback"] != null) {
return RecordedCsatChatMessage(
theme: theme,
l10n: widget.l10n,
- message: message,
+ message: types.CustomMessage(
+ author: message.author, id: message.id),
maxWidth: messageWidth,
);
}
return CSATChatMessage(
- theme: theme,
- l10n: widget.l10n,
- message: message,
- maxWidth: messageWidth,
- sendCsatResults: (rating, feedback){
- chatwootClient?.sendCsatSurveyResults(message.metadata!['conversationUuid'], rating, feedback);
- },
+ theme: theme,
+ l10n: widget.l10n,
+ message: types.CustomMessage(
+ author: message.author, id: message.id),
+ maxWidth: messageWidth,
+ sendCsatResults: (rating, feedback) {
+ chatwootClient?.sendCsatSurveyResults(
+ message.metadata!['conversationUuid'],
+ rating,
+ feedback);
+ },
);
},
l10n: widget.l10n,
),
),
),
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Image.asset(
- "assets/logo_grey.png",
- package: 'chatwoot_sdk',
- width: 15,
- height: 15,
- ),
- Padding(
- padding: const EdgeInsets.only(left: 8.0),
- child: Text(
- "Powered by Chatwoot",
- style: TextStyle(color: Colors.black45, fontSize: 12),
- ),
- )
- ],
- ),
+ const SizedBox(
+ height: 24,
)
],
),
@@ -810,13 +800,11 @@ class _ChatwootChatState extends State with WidgetsBindingObserver
videoPreviewLoader.dispose();
LinkMetadata.dispose();
controller.player.dispose();
- _messages.forEach((m){
- if(m is types.VideoMessage){
- final controller= m.metadata?["controller"] as VideoController?;
+ _messages.forEach((m) {
+ if (m is types.VideoMessage) {
+ final controller = m.metadata?["controller"] as VideoController?;
controller?.player.dispose();
}
});
}
}
-
-
diff --git a/lib/ui/chatwoot_chat_theme.dart b/lib/ui/chatwoot_chat_theme.dart
index 5086982..6023ea9 100644
--- a/lib/ui/chatwoot_chat_theme.dart
+++ b/lib/ui/chatwoot_chat_theme.dart
@@ -1,4 +1,3 @@
-
import 'package:flutter/material.dart';
import 'package:flutter_chat_ui/flutter_chat_ui.dart';
@@ -57,13 +56,13 @@ class ChatwootChatTheme extends ChatTheme {
),
Color receivedMessageDocumentIconColor = PRIMARY,
TextStyle receivedMessageLinkDescriptionTextStyle = const TextStyle(
- color: primary,
+ color: Colors.blue, // primary,
fontSize: 14,
fontWeight: FontWeight.w400,
height: 1.428,
),
TextStyle receivedMessageLinkTitleTextStyle = const TextStyle(
- color: primary,
+ color: Colors.blue, // primary,
fontSize: 16,
fontWeight: FontWeight.w800,
height: 1.375,
@@ -99,7 +98,7 @@ class ChatwootChatTheme extends ChatTheme {
),
List userAvatarNameColors = CHATWOOT_AVATAR_COLORS,
TextStyle userAvatarTextStyle = const TextStyle(
- color: primary,
+ color: Colors.blue, // primary,
fontSize: 12,
fontWeight: FontWeight.w800,
height: 1.333,
@@ -113,34 +112,29 @@ class ChatwootChatTheme extends ChatTheme {
EdgeInsets? attachmentButtonMargin,
EdgeInsets dateDividerMargin = const EdgeInsets.all(8),
Color inputSurfaceTintColor = Colors.blueAccent,
- double inputElevation= 0,
+ double inputElevation = 0,
EdgeInsets inputMargin = const EdgeInsets.all(8),
- EdgeInsets inputPadding= const EdgeInsets.all(8),
- double messageInsetsHorizontal= 8,
- double messageInsetsVertical= 8,
- double messageMaxWidth= 500,
- TextStyle receivedEmojiMessageTextStyle= const TextStyle(),
- EdgeInsets sendButtonMargin= const EdgeInsets.all(8),
- TextStyle sentEmojiMessageTextStyle= const TextStyle(),
- EdgeInsets statusIconPadding= const EdgeInsets.all(8),
- SystemMessageTheme systemMessageTheme= const SystemMessageTheme(
- margin: const EdgeInsets.all(8),
- textStyle: const TextStyle()
- ),
- TypingIndicatorTheme typingIndicatorTheme= const TypingIndicatorTheme(
+ EdgeInsets inputPadding = const EdgeInsets.all(8),
+ double messageInsetsHorizontal = 8,
+ double messageInsetsVertical = 8,
+ double messageMaxWidth = 500,
+ TextStyle receivedEmojiMessageTextStyle = const TextStyle(),
+ EdgeInsets sendButtonMargin = const EdgeInsets.all(8),
+ TextStyle sentEmojiMessageTextStyle = const TextStyle(),
+ EdgeInsets statusIconPadding = const EdgeInsets.all(8),
+ SystemMessageTheme systemMessageTheme = const SystemMessageTheme(
+ margin: const EdgeInsets.all(8), textStyle: const TextStyle()),
+ TypingIndicatorTheme typingIndicatorTheme = const TypingIndicatorTheme(
animatedCirclesColor: primary,
animatedCircleSize: 8,
bubbleBorder: const BorderRadius.all(const Radius.circular(8)),
bubbleColor: Colors.white,
countAvatarColor: primary,
countTextColor: Colors.black87,
- multipleUserTextStyle: const TextStyle()
- ),
- UnreadHeaderTheme unreadHeaderTheme= const UnreadHeaderTheme(
- color: CHATWOOT_COLOR_PRIMARY,
- textStyle: const TextStyle()
- ),
- Color userAvatarImageBackgroundColor= Colors.white,
+ multipleUserTextStyle: const TextStyle()),
+ UnreadHeaderTheme unreadHeaderTheme = const UnreadHeaderTheme(
+ color: CHATWOOT_COLOR_PRIMARY, textStyle: const TextStyle()),
+ Color userAvatarImageBackgroundColor = Colors.white,
}) : super(
attachmentButtonIcon: attachmentButtonIcon,
backgroundColor: backgroundColor,
diff --git a/lib/ui/video_preview.dart b/lib/ui/video_preview.dart
index 821e5eb..5a9e492 100644
--- a/lib/ui/video_preview.dart
+++ b/lib/ui/video_preview.dart
@@ -1,5 +1,3 @@
-
-
import 'dart:async';
import 'dart:collection';
import 'dart:typed_data';
@@ -8,28 +6,24 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart';
-class VideoMessagePreview{
+class VideoMessagePreview {
final ui.FrameInfo? firstFrame;
final double width;
final double height;
-
- VideoMessagePreview({this.firstFrame, this.width=0, this.height=0});
-
-
+ VideoMessagePreview({this.firstFrame, this.width = 0, this.height = 0});
}
-class VideoMessagePreviewJob{
- final String jobId ;
+class VideoMessagePreviewJob {
+ final String jobId;
final String uri;
VideoMessagePreviewJob({required this.jobId, required this.uri});
-
}
-class VideoMessagePreviewResult{
+class VideoMessagePreviewResult {
///Fetch preview job identification
- final String jobId ;
+ final String jobId;
///Video uri
final String uri;
@@ -37,12 +31,11 @@ class VideoMessagePreviewResult{
///Preview results
final VideoMessagePreview preview;
- VideoMessagePreviewResult({required this.jobId, required this.uri, required this.preview});
-
+ VideoMessagePreviewResult(
+ {required this.jobId, required this.uri, required this.preview});
}
-
-class VideoPreviewLoader{
+class VideoPreviewLoader {
///Video controller for loading first video frame. See [ChatwootChat.build]
VideoController controller;
@@ -50,53 +43,54 @@ class VideoPreviewLoader{
final _previewJobQueue = Queue();
///Stream to send preview results
- final _previewResponseStreamController = StreamController();
+ final _previewResponseStreamController =
+ StreamController();
StreamSubscription? _previewResponseStreamSubscription;
VideoPreviewLoader({required this.controller});
- void getPreview({required String jobId, required String uri})async{
- if(_previewJobQueue.isEmpty){
+ void getPreview({required String jobId, required String uri}) async {
+ if (_previewJobQueue.isEmpty) {
//no video previews are being fetched
_previewJobQueue.add(VideoMessagePreviewJob(jobId: jobId, uri: uri));
_fromUri(jobId, uri);
- }else{
+ } else {
//ongoing video preview fetch. add to queue
_previewJobQueue.add(VideoMessagePreviewJob(jobId: jobId, uri: uri));
}
}
-
- Future _getCacheVideoPreview(String jobId, String uri) async{
- final fileInfo = await CachedNetworkImageProvider.defaultCacheManager.getFileFromCache(uri);
- if(fileInfo != null){
+ Future _getCacheVideoPreview(
+ String jobId, String uri) async {
+ final fileInfo = await CachedNetworkImageProvider(uri)
+ .cacheManager!
+ .getFileFromCache(uri);
+ if (fileInfo != null) {
// return cached preview
- final codec = await ui.instantiateImageCodec(await fileInfo.file.readAsBytes());
+ final codec =
+ await ui.instantiateImageCodec(await fileInfo.file.readAsBytes());
final frame = await codec.getNextFrame();
final firstframe = frame;
final width = frame.image.width.toDouble();
final height = frame.image.height.toDouble();
final cachedPreview = VideoMessagePreview(
- firstFrame: firstframe,
- width: width,
- height: height
- );
+ firstFrame: firstframe, width: width, height: height);
return cachedPreview;
}
return null;
}
///Loads first frame from video url
- Future _fromUri(String jobId, String uri) async{
-
+ Future _fromUri(String jobId, String uri) async {
//check for cached preview
final cachedPreview = await _getCacheVideoPreview(jobId, uri);
- if(cachedPreview != null){
+ if (cachedPreview != null) {
// return cached preview
- _previewResponseStreamController.add(VideoMessagePreviewResult(jobId: jobId, uri: uri, preview: cachedPreview));
+ _previewResponseStreamController.add(VideoMessagePreviewResult(
+ jobId: jobId, uri: uri, preview: cachedPreview));
//check for pending jobs and execute
- if(_previewJobQueue.isNotEmpty){
+ if (_previewJobQueue.isNotEmpty) {
final job = _previewJobQueue.removeFirst();
_fromUri(job.jobId, job.uri);
}
@@ -112,10 +106,10 @@ class VideoPreviewLoader{
await controller.player.setVolume(0);
await controller.player.open(Media(uri));
await Future.delayed(Duration(seconds: 10));
- await controller.player.stream.position.firstWhere((d)=>d>Duration.zero);
+ await controller.player.stream.position
+ .firstWhere((d) => d > Duration.zero);
Uint8List? frameBytes = await controller.player.screenshot();
-
if (frameBytes != null) {
// Convert the Uint8List to a ui.Image
final codec = await ui.instantiateImageCodec(frameBytes);
@@ -123,9 +117,10 @@ class VideoPreviewLoader{
firstframe = frame;
width = frame.image.width.toDouble();
height = frame.image.height.toDouble();
- await CachedNetworkImageProvider.defaultCacheManager.putFile(uri, frameBytes);
+ await CachedNetworkImageProvider(uri)
+ .cacheManager!
+ .putFile(uri, frameBytes);
}
-
} catch (e) {
print('Error capturing first frame: $e');
} finally {
@@ -134,29 +129,25 @@ class VideoPreviewLoader{
}
final p = VideoMessagePreview(
- firstFrame: firstframe,
- width: width,
- height: height
- );
-
+ firstFrame: firstframe, width: width, height: height);
//send preview result
- _previewResponseStreamController.add(
- VideoMessagePreviewResult(jobId: jobId, uri: uri, preview: p)
- );
+ _previewResponseStreamController
+ .add(VideoMessagePreviewResult(jobId: jobId, uri: uri, preview: p));
//check for pending jobs and execute
- if(_previewJobQueue.isNotEmpty){
+ if (_previewJobQueue.isNotEmpty) {
final job = _previewJobQueue.removeFirst();
_fromUri(job.jobId, job.uri);
}
}
- listen(void Function(VideoMessagePreviewResult) callback){
- _previewResponseStreamSubscription = _previewResponseStreamController.stream.listen(callback);
+ listen(void Function(VideoMessagePreviewResult) callback) {
+ _previewResponseStreamSubscription =
+ _previewResponseStreamController.stream.listen(callback);
}
- dispose(){
+ dispose() {
_previewResponseStreamSubscription?.cancel();
}
}
diff --git a/pubspec.lock b/pubspec.lock
index c213b36..bb4ca32 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -122,26 +122,26 @@ packages:
dependency: "direct main"
description:
name: cached_network_image
- sha256: "4a5d8d2c728b0f3d0245f69f921d7be90cae4c2fd5288f773088672c0893f819"
+ sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f"
url: "https://pub.dev"
source: hosted
- version: "3.4.0"
+ version: "3.3.1"
cached_network_image_platform_interface:
dependency: transitive
description:
name: cached_network_image_platform_interface
- sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
+ sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f"
url: "https://pub.dev"
source: hosted
- version: "4.1.1"
+ version: "4.0.0"
cached_network_image_web:
dependency: transitive
description:
name: cached_network_image_web
- sha256: "6322dde7a5ad92202e64df659241104a43db20ed594c41ca18de1014598d7996"
+ sha256: "205d6a9f1862de34b93184f22b9d2d94586b2f05c581d546695e3d8f6a805cd7"
url: "https://pub.dev"
source: hosted
- version: "1.3.0"
+ version: "1.2.0"
characters:
dependency: transitive
description:
@@ -191,7 +191,7 @@ packages:
source: hosted
version: "3.1.2"
crypto:
- dependency: "direct main"
+ dependency: transitive
description:
name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
@@ -234,18 +234,10 @@ packages:
dependency: "direct main"
description:
name: dio
- sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260"
- url: "https://pub.dev"
- source: hosted
- version: "5.7.0"
- dio_web_adapter:
- dependency: transitive
- description:
- name: dio_web_adapter
- sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8"
+ sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8"
url: "https://pub.dev"
source: hosted
- version: "2.0.0"
+ version: "4.0.6"
easy_image_viewer:
dependency: "direct main"
description:
@@ -303,10 +295,10 @@ packages:
dependency: transitive
description:
name: flutter_cache_manager
- sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
+ sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
url: "https://pub.dev"
source: hosted
- version: "3.4.1"
+ version: "3.3.1"
flutter_chat_types:
dependency: "direct main"
description:
@@ -343,18 +335,18 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
- sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
+ sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
url: "https://pub.dev"
source: hosted
- version: "5.0.0"
+ version: "2.0.3"
flutter_markdown:
dependency: "direct main"
description:
name: flutter_markdown
- sha256: "999a4e3cb3e1532a971c86d6c73a480264f6a687959d4887cb4e2990821827e4"
+ sha256: "255b00afa1a7bad19727da6a7780cf3db6c3c12e68d302d85e0ff1fdf173db9e"
url: "https://pub.dev"
source: hosted
- version: "0.7.4+2"
+ version: "0.7.4+3"
flutter_parsed_text:
dependency: transitive
description:
@@ -367,10 +359,10 @@ packages:
dependency: "direct main"
description:
name: flutter_secure_storage
- sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0"
+ sha256: "22dbf16f23a4bcf9d35e51be1c84ad5bb6f627750565edd70dab70f3ff5fff8f"
url: "https://pub.dev"
source: hosted
- version: "9.2.2"
+ version: "8.1.0"
flutter_secure_storage_linux:
dependency: transitive
description:
@@ -407,10 +399,10 @@ packages:
dependency: transitive
description:
name: flutter_secure_storage_windows
- sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709
+ sha256: "38f9501c7cb6f38961ef0e1eacacee2b2d4715c63cc83fe56449c4d3d0b47255"
url: "https://pub.dev"
source: hosted
- version: "3.1.2"
+ version: "2.1.1"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -421,6 +413,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ freezed_annotation:
+ dependency: transitive
+ description:
+ name: freezed_annotation
+ sha256: "70776c4541e5cacfe45bcaf00fe79137b8c61aa34fb5765a05ce6c57fd72c6e9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.14.3"
frontend_server_client:
dependency: transitive
description:
@@ -481,10 +481,10 @@ packages:
dependency: transitive
description:
name: http
- sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
+ sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
url: "https://pub.dev"
source: hosted
- version: "1.2.2"
+ version: "0.13.6"
http_multi_server:
dependency: transitive
description:
@@ -513,10 +513,10 @@ packages:
dependency: "direct main"
description:
name: intl
- sha256: "99f282cb0e02edcbbf8c6b3bbc7c90b65635156c412e58f3975a7e55284ce685"
+ sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
url: "https://pub.dev"
source: hosted
- version: "0.20.0"
+ version: "0.17.0"
io:
dependency: transitive
description:
@@ -585,10 +585,10 @@ packages:
dependency: transitive
description:
name: lints
- sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
+ sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev"
source: hosted
- version: "5.0.0"
+ version: "2.1.1"
logging:
dependency: transitive
description:
@@ -710,7 +710,7 @@ packages:
source: hosted
version: "1.15.0"
mime:
- dependency: "direct main"
+ dependency: transitive
description:
name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
@@ -873,18 +873,18 @@ packages:
dependency: "direct main"
description:
name: riverpod
- sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959"
+ sha256: "13cbe0e17b659f38027986df967b3eaf7f42c519786352167fc3db1be44eae07"
url: "https://pub.dev"
source: hosted
- version: "2.6.1"
+ version: "0.14.0+3"
rxdart:
dependency: transitive
description:
name: rxdart
- sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
+ sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
url: "https://pub.dev"
source: hosted
- version: "0.28.0"
+ version: "0.27.7"
safe_local_storage:
dependency: transitive
description:
@@ -994,14 +994,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.0"
- sprintf:
- dependency: transitive
- description:
- name: sprintf
- sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
- url: "https://pub.dev"
- source: hosted
- version: "7.0.0"
sqflite:
dependency: transitive
description:
@@ -1054,10 +1046,10 @@ packages:
dependency: transitive
description:
name: state_notifier
- sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
+ sha256: "8fe42610f179b843b12371e40db58c9444f8757f8b69d181c97e50787caed289"
url: "https://pub.dev"
source: hosted
- version: "1.0.0"
+ version: "0.7.2+1"
stream_channel:
dependency: "direct main"
description:
@@ -1206,10 +1198,10 @@ packages:
dependency: "direct main"
description:
name: uuid
- sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
+ sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
url: "https://pub.dev"
source: hosted
- version: "4.5.1"
+ version: "3.0.7"
vector_math:
dependency: transitive
description:
@@ -1274,22 +1266,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.5.1"
- web_socket:
- dependency: transitive
- description:
- name: web_socket
- sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
- url: "https://pub.dev"
- source: hosted
- version: "0.1.6"
web_socket_channel:
dependency: "direct main"
description:
name: web_socket_channel
- sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
+ sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
url: "https://pub.dev"
source: hosted
- version: "3.0.1"
+ version: "2.4.5"
webview_flutter:
dependency: "direct main"
description:
@@ -1326,10 +1310,10 @@ packages:
dependency: transitive
description:
name: win32
- sha256: "84ba388638ed7a8cb3445a320c8273136ab2631cd5f2c57888335504ddab1bc2"
+ sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69"
url: "https://pub.dev"
source: hosted
- version: "5.8.0"
+ version: "5.9.0"
xdg_directories:
dependency: transitive
description:
@@ -1355,5 +1339,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
- dart: ">=3.5.3 <4.0.0"
+ dart: ">=3.5.0 <4.0.0"
flutter: ">=3.24.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index ec204ea..8b6696f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,10 +1,11 @@
name: chatwoot_sdk
description: A flutter client sdk for chatwoot. Integrate Chatwoot flutter client into your flutter app and talk to your visitors/users in real time.
-version: 0.1.0
+version: 0.0.9
homepage: https://github.com/chatwoot/chatwoot-flutter-sdk
environment:
- sdk: "^3.5.3"
+ sdk: ">=3.0.0 <4.0.0"
+ flutter: ">=1.17.0"
dependencies:
flutter:
@@ -12,29 +13,27 @@ dependencies:
flutter_chat_ui: ^1.1.9
hive: ^2.2.3
hive_flutter: ^1.1.0
- uuid: ^4.5.1
- web_socket_channel: ^3.0.1
+ uuid: ^3.0.4
+ web_socket_channel: ^2.1.0
json_annotation: ^4.0.1
- dio: ^5.7.0
+ dio: ^4.0.0
equatable: ^2.0.3
- riverpod: ^2.6.1
+ riverpod: ^0.14.0+3
synchronized: ^3.0.0
- intl: ^0.20.0
+ intl: ^0.17.0
flutter_chat_types: ^3.6.2
stream_channel: ^2.1.0
async: ^2.5.0
- flutter_secure_storage: ^9.2.2
- url_launcher: ^6.3.1
+ webview_flutter: ^4.0.6
+ flutter_secure_storage: ^8.0.0
+ url_launcher: ^6.1.10
path_provider: ^2.0.13
- mime: ^2.0.0
- media_kit: ^1.1.11
- media_kit_video: ^1.2.5
- media_kit_libs_video: ^1.0.5
+ cached_network_image: ^3.3.1
+ media_kit: ^1.1.11 # Primary package.
+ media_kit_video: ^1.2.5 # For video rendering.
+ media_kit_libs_video: ^1.0.5 # Native video dependencies.
easy_image_viewer: ^1.5.1
- cached_network_image: ^3.4.0
- flutter_markdown: ^0.7.4+2
- webview_flutter: ^4.10.0
- crypto: ^3.0.6
+ flutter_markdown: ^0.7.4+3
dev_dependencies:
flutter_test:
@@ -43,7 +42,7 @@ dev_dependencies:
json_serializable: ^6.6.1
hive_generator: ^2.0.0
build_runner: ^2.3.3
- flutter_lints: ^5.0.0
+ flutter_lints: ^2.0.1
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
diff --git a/test/data/remote/chatwoot_client_auth_service_test.dart b/test/data/remote/chatwoot_client_auth_service_test.dart
index d16b935..b747316 100644
--- a/test/data/remote/chatwoot_client_auth_service_test.dart
+++ b/test/data/remote/chatwoot_client_auth_service_test.dart
@@ -86,7 +86,7 @@ void main() {
'Given contact creation fails when createNewContact is called, then throw error',
() async {
//GIVEN
- final testError = DioException(requestOptions: RequestOptions(path: ""));
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
when(mockDio.post(any, data: testUser.toJson())).thenThrow(testError);
//WHEN
@@ -146,7 +146,7 @@ void main() {
'Given conversation creation fails when createNewConversation is called, then throw error',
() async {
//GIVEN
- final testError = DioException(requestOptions: RequestOptions(path: ""));
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
when(mockDio.post(any)).thenThrow(testError);
//WHEN
diff --git a/test/data/remote/chatwoot_client_service_test.dart b/test/data/remote/chatwoot_client_service_test.dart
index e8d90bc..2e080c9 100644
--- a/test/data/remote/chatwoot_client_service_test.dart
+++ b/test/data/remote/chatwoot_client_service_test.dart
@@ -27,7 +27,8 @@ void main() {
final unauthenticatedmockDio = MockDio();
setUpAll(() {
- clientService = ChatwootClientServiceImpl(testBaseUrl, dio: mockDio, uDio: unauthenticatedmockDio);
+ clientService = ChatwootClientServiceImpl(testBaseUrl,
+ dio: mockDio, uDio: unauthenticatedmockDio);
});
_createSuccessResponse(body) {
@@ -52,16 +53,16 @@ void main() {
await TestResourceUtil.readJsonResource(fileName: "message");
final request =
ChatwootNewMessageRequest(content: "test message", echoId: "id");
- when(mockDio.post(any, data: anyNamed("data"))).thenAnswer(
- (invocation){
- assert(invocation.namedArguments[Symbol("data")] is FormData);
- final form = invocation.namedArguments[Symbol("data")] as FormData;
- final messageContent = form.fields.firstWhere((f)=>f.key == "content").value;
- final echoId = form.fields.firstWhere((f)=>f.key == "echo_id").value;
- expect(messageContent, request.content);
- expect(echoId, request.echoId);
- return Future.value(_createSuccessResponse(responseBody));
- });
+ when(mockDio.post(any, data: anyNamed("data"))).thenAnswer((invocation) {
+ assert(invocation.namedArguments[Symbol("data")] is FormData);
+ final form = invocation.namedArguments[Symbol("data")] as FormData;
+ final messageContent =
+ form.fields.firstWhere((f) => f.key == "content").value;
+ final echoId = form.fields.firstWhere((f) => f.key == "echo_id").value;
+ expect(messageContent, request.content);
+ expect(echoId, request.echoId);
+ return Future.value(_createSuccessResponse(responseBody));
+ });
//WHEN
final result = await clientService.createMessage(request);
@@ -97,7 +98,7 @@ void main() {
'Given sending message fails when createMessage is called, then throw error',
() async {
//GIVEN
- final testError = DioException(requestOptions: RequestOptions(path: ""));
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
final request =
ChatwootNewMessageRequest(content: "test message", echoId: "id");
when(mockDio.post(any, data: anyNamed("data"))).thenThrow(testError);
@@ -159,7 +160,7 @@ void main() {
'Given fetch messages fails when getAllMessages is called, then throw error',
() async {
//GIVEN
- final testError = DioException(requestOptions: RequestOptions(path: ""));
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
when(mockDio.get(any)).thenThrow(testError);
//WHEN
@@ -217,7 +218,7 @@ void main() {
'Given fetch contact fails when getContact is called, then throw error',
() async {
//GIVEN
- final testError = DioException(requestOptions: RequestOptions(path: ""));
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
when(mockDio.get(any)).thenThrow(testError);
//WHEN
@@ -277,7 +278,7 @@ void main() {
'Given fetch conversations fails when getConversations is called, then throw error',
() async {
//GIVEN
- final testError = DioException(requestOptions: RequestOptions(path: ""));
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
when(mockDio.get(any)).thenThrow(testError);
//WHEN
@@ -338,7 +339,7 @@ void main() {
() async {
//GIVEN
final update = {"name": "Updated name"};
- final testError = DioException(requestOptions: RequestOptions(path: ""));
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
when(mockDio.patch(any, data: update)).thenThrow(testError);
//WHEN
@@ -357,156 +358,159 @@ void main() {
test(
'Given message is successfully updated when updateMessage is called, then return updated message',
- () async {
- //GIVEN
- final responseBody =
+ () async {
+ //GIVEN
+ final responseBody =
await TestResourceUtil.readJsonResource(fileName: "message");
- final testMessageId = "id";
- final update = {"content": "Updated content"};
- when(mockDio.patch(any, data: update)).thenAnswer(
- (_) => Future.value(_createSuccessResponse(responseBody)));
+ final testMessageId = "id";
+ final update = {"content": "Updated content"};
+ when(mockDio.patch(any, data: update)).thenAnswer(
+ (_) => Future.value(_createSuccessResponse(responseBody)));
- //WHEN
- final result = await clientService.updateMessage(testMessageId, update);
+ //WHEN
+ final result = await clientService.updateMessage(testMessageId, update);
- //THEN
- expect(result, ChatwootMessage.fromJson(responseBody));
- });
+ //THEN
+ expect(result, ChatwootMessage.fromJson(responseBody));
+ });
test(
'Given message update returns with error response when updateMessage is called, then throw error',
- () async {
- //GIVEN
- final testMessageId = "id";
- final update = {"content": "Updated content"};
- when(mockDio.patch(any, data: update)).thenAnswer(
- (_) => Future.value(_createErrorResponse(statusCode: 401, body: {})));
-
- //WHEN
- ChatwootClientException? chatwootClientException;
- try {
- await clientService.updateMessage(testMessageId, update);
- } on ChatwootClientException catch (e) {
- chatwootClientException = e;
- }
-
- //THEN
- verify(mockDio.patch(argThat(contains(testMessageId)), data: update));
- expect(chatwootClientException, isNotNull);
- expect(chatwootClientException!.type,
- equals(ChatwootClientExceptionType.UPDATE_MESSAGE_FAILED));
- });
+ () async {
+ //GIVEN
+ final testMessageId = "id";
+ final update = {"content": "Updated content"};
+ when(mockDio.patch(any, data: update)).thenAnswer(
+ (_) => Future.value(_createErrorResponse(statusCode: 401, body: {})));
+
+ //WHEN
+ ChatwootClientException? chatwootClientException;
+ try {
+ await clientService.updateMessage(testMessageId, update);
+ } on ChatwootClientException catch (e) {
+ chatwootClientException = e;
+ }
+
+ //THEN
+ verify(mockDio.patch(argThat(contains(testMessageId)), data: update));
+ expect(chatwootClientException, isNotNull);
+ expect(chatwootClientException!.type,
+ equals(ChatwootClientExceptionType.UPDATE_MESSAGE_FAILED));
+ });
test(
'Given message update fails when updateMessage is called, then throw error',
- () async {
- //GIVEN
- final testMessageId = "id";
- final update = {"content": "Updated content"};
- final testError = DioException(requestOptions: RequestOptions(path: ""));
- when(mockDio.patch(any, data: update)).thenThrow(testError);
-
- //WHEN
- ChatwootClientException? chatwootClientException;
- try {
- await clientService.updateMessage(testMessageId, update);
- } on ChatwootClientException catch (e) {
- chatwootClientException = e;
- }
-
- //THEN
- verify(mockDio.patch(argThat(contains(testMessageId)), data: update));
- expect(chatwootClientException, isNotNull);
- expect(chatwootClientException!.type,
- equals(ChatwootClientExceptionType.UPDATE_MESSAGE_FAILED));
- });
+ () async {
+ //GIVEN
+ final testMessageId = "id";
+ final update = {"content": "Updated content"};
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
+ when(mockDio.patch(any, data: update)).thenThrow(testError);
+
+ //WHEN
+ ChatwootClientException? chatwootClientException;
+ try {
+ await clientService.updateMessage(testMessageId, update);
+ } on ChatwootClientException catch (e) {
+ chatwootClientException = e;
+ }
+
+ //THEN
+ verify(mockDio.patch(argThat(contains(testMessageId)), data: update));
+ expect(chatwootClientException, isNotNull);
+ expect(chatwootClientException!.type,
+ equals(ChatwootClientExceptionType.UPDATE_MESSAGE_FAILED));
+ });
test(
'Given csat survey is successfully sent when sendCsatFeedBack is called, then return feedback response',
- () async {
- //GIVEN
- final responseBody =
+ () async {
+ //GIVEN
+ final responseBody =
await TestResourceUtil.readJsonResource(fileName: "csat_feedback");
- final testConversationUuid = "conversation-uuid";
- final feedbackRequest = SendCsatSurveyRequest(rating: 1, feedbackMessage: "test message");
- final requestBody = {
- "message":{
- "submitted_values":{
- "csat_survey_response": feedbackRequest.toJson()
- }
- }
- };
- when(unauthenticatedmockDio.put(any, data: requestBody)).thenAnswer(
- (_) => Future.value(_createSuccessResponse(responseBody)));
-
- //WHEN
- final result = await clientService.sendCsatFeedBack(testConversationUuid, feedbackRequest);
-
- //THEN
- expect(result, CsatSurveyFeedbackResponse.fromJson(responseBody));
- });
+ final testConversationUuid = "conversation-uuid";
+ final feedbackRequest =
+ SendCsatSurveyRequest(rating: 1, feedbackMessage: "test message");
+ final requestBody = {
+ "message": {
+ "submitted_values": {"csat_survey_response": feedbackRequest.toJson()}
+ }
+ };
+ when(unauthenticatedmockDio.put(any, data: requestBody)).thenAnswer(
+ (_) => Future.value(_createSuccessResponse(responseBody)));
+
+ //WHEN
+ final result = await clientService.sendCsatFeedBack(
+ testConversationUuid, feedbackRequest);
+
+ //THEN
+ expect(result, CsatSurveyFeedbackResponse.fromJson(responseBody));
+ });
test(
'Given send csat survey returns with error response when sendCsatFeedBack is called, then throw error',
- () async {
- //GIVEN
- final testConversationUuid = "conversation-uuid";
- final feedbackRequest = SendCsatSurveyRequest(rating: 1, feedbackMessage: "test message");
- final requestBody = {
- "message":{
- "submitted_values":{
- "csat_survey_response": feedbackRequest.toJson()
- }
- }
- };
- when(unauthenticatedmockDio.put(any, data: requestBody)).thenAnswer(
- (_) => Future.value(_createErrorResponse(statusCode: 500, body: {})));
-
- //WHEN
- ChatwootClientException? chatwootClientException;
- try {
- await clientService.sendCsatFeedBack(testConversationUuid, feedbackRequest);
- } on ChatwootClientException catch (e) {
- chatwootClientException = e;
- }
-
- //THEN
- verify(unauthenticatedmockDio.put(argThat(contains(testConversationUuid)), data: requestBody));
- expect(chatwootClientException, isNotNull);
- expect(chatwootClientException!.type,
- equals(ChatwootClientExceptionType.SEND_CSAT_FEEDBACK));
- });
+ () async {
+ //GIVEN
+ final testConversationUuid = "conversation-uuid";
+ final feedbackRequest =
+ SendCsatSurveyRequest(rating: 1, feedbackMessage: "test message");
+ final requestBody = {
+ "message": {
+ "submitted_values": {"csat_survey_response": feedbackRequest.toJson()}
+ }
+ };
+ when(unauthenticatedmockDio.put(any, data: requestBody)).thenAnswer(
+ (_) => Future.value(_createErrorResponse(statusCode: 500, body: {})));
+
+ //WHEN
+ ChatwootClientException? chatwootClientException;
+ try {
+ await clientService.sendCsatFeedBack(
+ testConversationUuid, feedbackRequest);
+ } on ChatwootClientException catch (e) {
+ chatwootClientException = e;
+ }
+
+ //THEN
+ verify(unauthenticatedmockDio.put(argThat(contains(testConversationUuid)),
+ data: requestBody));
+ expect(chatwootClientException, isNotNull);
+ expect(chatwootClientException!.type,
+ equals(ChatwootClientExceptionType.SEND_CSAT_FEEDBACK));
+ });
test(
'Given send csat feedback fails when sendCsatFeedBack is called, then throw error',
- () async {
- //GIVEN
- final testConversationUuid = "conversation-uuid";
- final feedbackRequest = SendCsatSurveyRequest(rating: 1, feedbackMessage: "test message");
- final testError = DioException(requestOptions: RequestOptions(path: ""));
- final requestBody = {
- "message":{
- "submitted_values":{
- "csat_survey_response": feedbackRequest.toJson()
- }
- }
- };
- when(unauthenticatedmockDio.put(any, data: requestBody)).thenThrow(testError);
-
- //WHEN
- ChatwootClientException? chatwootClientException;
- try {
- await clientService.sendCsatFeedBack(testConversationUuid, feedbackRequest);
- } on ChatwootClientException catch (e) {
- chatwootClientException = e;
- }
-
- //THEN
- verify(unauthenticatedmockDio.put(argThat(contains(testConversationUuid)), data: requestBody));
- expect(chatwootClientException, isNotNull);
- expect(chatwootClientException!.type,
- equals(ChatwootClientExceptionType.SEND_CSAT_FEEDBACK));
- });
+ () async {
+ //GIVEN
+ final testConversationUuid = "conversation-uuid";
+ final feedbackRequest =
+ SendCsatSurveyRequest(rating: 1, feedbackMessage: "test message");
+ final testError = DioError(requestOptions: RequestOptions(path: ""));
+ final requestBody = {
+ "message": {
+ "submitted_values": {"csat_survey_response": feedbackRequest.toJson()}
+ }
+ };
+ when(unauthenticatedmockDio.put(any, data: requestBody))
+ .thenThrow(testError);
+
+ //WHEN
+ ChatwootClientException? chatwootClientException;
+ try {
+ await clientService.sendCsatFeedBack(
+ testConversationUuid, feedbackRequest);
+ } on ChatwootClientException catch (e) {
+ chatwootClientException = e;
+ }
+
+ //THEN
+ verify(unauthenticatedmockDio.put(argThat(contains(testConversationUuid)),
+ data: requestBody));
+ expect(chatwootClientException, isNotNull);
+ expect(chatwootClientException!.type,
+ equals(ChatwootClientExceptionType.SEND_CSAT_FEEDBACK));
+ });
test(
'Given websocket connection is successful when startWebSocketConnection is called, then subscribe for events',