From ae8dd814d544bf3dd605497e4ae91fdc626d51b7 Mon Sep 17 00:00:00 2001
From: abedelaziz-deriv <135210555+abedelaziz-deriv@users.noreply.github.com>
Date: Mon, 5 Aug 2024 16:45:50 +0800
Subject: [PATCH] Minor code refactoring (#8)
---
CHANGELOG.md | 5 ++
README.md | 2 +-
assets/live_chat.js | 84 +++++++++++++++++++
example/pubspec.lock | 6 +-
.../live_chat_plus/assets/live_chat.js | 84 +++++++++++++++++++
example/web/index.html | 2 +-
ios/Classes/LiveChatPlugin.swift | 8 +-
lib/_internal/live_chat_web.dart | 6 +-
lib/src/js/js_helper_web.dart | 5 ++
lib/src/js/js_library.dart | 7 ++
lib/src/live_chat.dart | 45 +++++-----
lib/src/live_chat_method_channel.dart | 38 ++++-----
lib/src/live_chat_platform_interface.dart | 9 +-
pubspec.yaml | 10 ++-
14 files changed, 256 insertions(+), 55 deletions(-)
create mode 100644 assets/live_chat.js
create mode 100644 example/web/assets/packages/live_chat_plus/assets/live_chat.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 26c0b10..79f9927 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.0.5
+
+* Minor code refactoring.
+* Fixed a bug in iOS when passing null customParams.
+
## 1.0.4
* Updated README
diff --git a/README.md b/README.md
index 45bf5eb..d3e0688 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Step 2: To avoid issues with proguard enabled, include the following to proguard
### Web
Inside index.html file, add this line inside `
` tag:
```html
-
+
```
## Usage
diff --git a/assets/live_chat.js b/assets/live_chat.js
new file mode 100644
index 0000000..238be5a
--- /dev/null
+++ b/assets/live_chat.js
@@ -0,0 +1,84 @@
+function startLiveChat(license, userName, email) {
+ window.__lc = window.__lc || {};
+ window.__lc.license = license;;
+ window.__lc.asyncInit = true;
+ (function(n, t, c) {
+ function i(n) {
+ return e._h ? e._h.apply(null, n) : e._q.push(n)
+ }
+ var e = {
+ _q: [],
+ _h: null,
+ _v: "2.0",
+ on: function() {
+ i(["on", c.call(arguments)])
+ },
+ once: function() {
+ i(["once", c.call(arguments)])
+ },
+ off: function() {
+ i(["off", c.call(arguments)])
+ },
+ get: function() {
+ if (!e._h) throw new Error("[LiveChatWidget] You can't use getters before load.");
+ return i(["get", c.call(arguments)])
+ },
+ call: function() {
+ i(["call", c.call(arguments)])
+ },
+ init: function() {
+ var n = t.createElement("script");
+ n.async = !0, n.type = "text/javascript", n.src = "https://cdn.livechatinc.com/tracking.js", t.head.appendChild(n)
+ }
+ };
+ !n.__lc.asyncInit && e.init(), n.LiveChatWidget = n.LiveChatWidget || e
+ }(window, document, [].slice));
+ window.LiveChatWidget.init();
+ window.LiveChatWidget.on('ready', function() {
+ window.eventProducer.emit('event', 'chatOpen');
+ if (window.LiveChatWidget && typeof window.LiveChatWidget.call === 'function') {
+ window.LiveChatWidget.call('set_customer_email', email);
+ window.LiveChatWidget.call('set_customer_name', userName);
+ }
+ });
+
+ if (window.LiveChatWidget && typeof window.LiveChatWidget.call === 'function') {
+ window.LiveChatWidget.call('maximize');
+ }
+
+ window.LiveChatWidget.on('new_event', onNewEvent);
+}
+
+function onNewEvent(event) {
+ window.eventProducer.emit('event', event.type);
+}
+
+function hideWindow() {
+ LiveChatWidget.call("hide");
+}
+
+function destroyWindow() {
+ LiveChatWidget.call("destroy");
+}
+
+
+class EventProducer {
+ constructor() {
+ this.listeners = {};
+ }
+
+ on(event, listener) {
+ if (!this.listeners[event]) {
+ this.listeners[event] = [];
+ }
+ this.listeners[event].push(listener);
+ }
+
+ emit(event, data) {
+ if (this.listeners[event]) {
+ this.listeners[event].forEach(listener => listener(data));
+ }
+ }
+}
+
+ window.eventProducer = new EventProducer();
diff --git a/example/pubspec.lock b/example/pubspec.lock
index d11fcd5..c7d2123 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -47,10 +47,10 @@ packages:
dependency: transitive
description:
name: js
- sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
+ sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
url: "https://pub.dev"
source: hosted
- version: "0.6.7"
+ version: "0.7.1"
lints:
dependency: transitive
description:
@@ -65,7 +65,7 @@ packages:
path: ".."
relative: true
source: path
- version: "1.0.3"
+ version: "1.0.5"
material_color_utilities:
dependency: transitive
description:
diff --git a/example/web/assets/packages/live_chat_plus/assets/live_chat.js b/example/web/assets/packages/live_chat_plus/assets/live_chat.js
new file mode 100644
index 0000000..238be5a
--- /dev/null
+++ b/example/web/assets/packages/live_chat_plus/assets/live_chat.js
@@ -0,0 +1,84 @@
+function startLiveChat(license, userName, email) {
+ window.__lc = window.__lc || {};
+ window.__lc.license = license;;
+ window.__lc.asyncInit = true;
+ (function(n, t, c) {
+ function i(n) {
+ return e._h ? e._h.apply(null, n) : e._q.push(n)
+ }
+ var e = {
+ _q: [],
+ _h: null,
+ _v: "2.0",
+ on: function() {
+ i(["on", c.call(arguments)])
+ },
+ once: function() {
+ i(["once", c.call(arguments)])
+ },
+ off: function() {
+ i(["off", c.call(arguments)])
+ },
+ get: function() {
+ if (!e._h) throw new Error("[LiveChatWidget] You can't use getters before load.");
+ return i(["get", c.call(arguments)])
+ },
+ call: function() {
+ i(["call", c.call(arguments)])
+ },
+ init: function() {
+ var n = t.createElement("script");
+ n.async = !0, n.type = "text/javascript", n.src = "https://cdn.livechatinc.com/tracking.js", t.head.appendChild(n)
+ }
+ };
+ !n.__lc.asyncInit && e.init(), n.LiveChatWidget = n.LiveChatWidget || e
+ }(window, document, [].slice));
+ window.LiveChatWidget.init();
+ window.LiveChatWidget.on('ready', function() {
+ window.eventProducer.emit('event', 'chatOpen');
+ if (window.LiveChatWidget && typeof window.LiveChatWidget.call === 'function') {
+ window.LiveChatWidget.call('set_customer_email', email);
+ window.LiveChatWidget.call('set_customer_name', userName);
+ }
+ });
+
+ if (window.LiveChatWidget && typeof window.LiveChatWidget.call === 'function') {
+ window.LiveChatWidget.call('maximize');
+ }
+
+ window.LiveChatWidget.on('new_event', onNewEvent);
+}
+
+function onNewEvent(event) {
+ window.eventProducer.emit('event', event.type);
+}
+
+function hideWindow() {
+ LiveChatWidget.call("hide");
+}
+
+function destroyWindow() {
+ LiveChatWidget.call("destroy");
+}
+
+
+class EventProducer {
+ constructor() {
+ this.listeners = {};
+ }
+
+ on(event, listener) {
+ if (!this.listeners[event]) {
+ this.listeners[event] = [];
+ }
+ this.listeners[event].push(listener);
+ }
+
+ emit(event, data) {
+ if (this.listeners[event]) {
+ this.listeners[event].forEach(listener => listener(data));
+ }
+ }
+}
+
+ window.eventProducer = new EventProducer();
diff --git a/example/web/index.html b/example/web/index.html
index 9bf2075..9353de8 100644
--- a/example/web/index.html
+++ b/example/web/index.html
@@ -32,7 +32,7 @@
live_chat_example
-
+
diff --git a/ios/Classes/LiveChatPlugin.swift b/ios/Classes/LiveChatPlugin.swift
index e4c60ee..6b78f49 100644
--- a/ios/Classes/LiveChatPlugin.swift
+++ b/ios/Classes/LiveChatPlugin.swift
@@ -30,7 +30,7 @@ public class LiveChatPlugin: NSObject, FlutterPlugin, LiveChatDelegate, FlutterS
let visitorName = (arguments["visitorName"] as? String)
let visitorEmail = (arguments["visitorEmail"] as? String)
let groupId = (arguments["groupId"] as? String)
- let customParams = (arguments["customParams"] as! [String: String])
+ let customParams = (arguments["customParams"] as? [String: String])
if licenseId == "" {
result(FlutterError(code: "", message: "LICENSE NUMBER EMPTY", details: nil))
@@ -40,8 +40,10 @@ public class LiveChatPlugin: NSObject, FlutterPlugin, LiveChatDelegate, FlutterS
LiveChat.email = visitorEmail
LiveChat.groupId = groupId
- for (key, value) in customParams {
- LiveChat.setVariable(withKey: key, value: value)
+ if(customParams != nil) {
+ for (key, value) in customParams! {
+ LiveChat.setVariable(withKey: key, value: value)
+ }
}
LiveChat.delegate = self
diff --git a/lib/_internal/live_chat_web.dart b/lib/_internal/live_chat_web.dart
index 2268843..025d52c 100644
--- a/lib/_internal/live_chat_web.dart
+++ b/lib/_internal/live_chat_web.dart
@@ -8,8 +8,10 @@ import 'package:js/js_util.dart' as js;
/// A web implementation of the LiveChatPlatform of the LiveChat plugin.
class LiveChatWeb extends LiveChatPlatform {
+ /// Constructs LiveChatWeb
LiveChatWeb();
+ /// Register livechat instance when web.
static void registerWith(Registrar registrar) {
LiveChatPlatform.instance = LiveChatWeb();
}
@@ -30,8 +32,8 @@ class LiveChatWeb extends LiveChatPlatform {
}
@override
- Stream? getLiveChatEventsStream() {
- eventProducer.on('event', js.allowInterop((data) {
+ Stream? getLiveChatEventsStream() {
+ eventProducer.on('event', js.allowInterop((dynamic data) {
_streamController.add(data);
}));
return _streamController.stream;
diff --git a/lib/src/js/js_helper_web.dart b/lib/src/js/js_helper_web.dart
index 1531573..c77514e 100644
--- a/lib/src/js/js_helper_web.dart
+++ b/lib/src/js/js_helper_web.dart
@@ -1,14 +1,19 @@
import 'js_library.dart';
+/// Helper class that handles calling external functions triggered with
+/// javascript.
class JSHelper {
+ /// Calls to open live chat window.
void callStartLiveChat(String licence, String userName, String email) {
startLiveChat(licence, userName, email);
}
+ /// Calls to close live chat window.
void callHideWindow() {
hideWindow();
}
+ /// Call to destroy live chat.
void callDestroyWindow() {
destroyWindow();
}
diff --git a/lib/src/js/js_library.dart b/lib/src/js/js_library.dart
index fac4c23..4bb2c90 100644
--- a/lib/src/js/js_library.dart
+++ b/lib/src/js/js_library.dart
@@ -1,18 +1,25 @@
import 'package:js/js.dart';
+/// Producer class that will be called in javascript.
@JS()
class EventProducer {
+ /// Triggers whenever a new event is emit in javascript. It should be listened
+ /// to in dart.
external void on(String event, Function listener);
}
+/// Exposes [eventProducer].
@JS('window.eventProducer')
external EventProducer get eventProducer;
+/// Triggers opening web live chat.
@JS()
external void startLiveChat(String licence, String userName, String email);
+/// Triggers hiding web live chat.
@JS()
external void hideWindow();
+/// Triggers destroying web live chat.
@JS()
external void destroyWindow();
diff --git a/lib/src/live_chat.dart b/lib/src/live_chat.dart
index e9ffb3b..8b89741 100644
--- a/lib/src/live_chat.dart
+++ b/lib/src/live_chat.dart
@@ -1,38 +1,43 @@
import 'package:live_chat_plus/src/live_chat_platform_interface.dart';
+/// Live Chat Plus plugin class.
class LiveChat {
- static final LiveChat _singleton = LiveChat._internal();
-
- factory LiveChat() {
- return _singleton;
- }
+ /// Constructs Livechat.
+ factory LiveChat() => _singleton;
LiveChat._internal();
+ static final LiveChat _singleton = LiveChat._internal();
+
+ /// Call to open the live chat window. It requires [licenseId], [username],
+ /// and [email].
+ /// In addition, optional [groupId] and [customParameters] can be passed if
+ /// needed.
Future openChatWindow({
required String licenseId,
required String username,
required String email,
String? groupId,
Map? customParameters,
- }) async {
- return LiveChatPlatform.instance.openChatWindow(
- licenseId: licenseId,
- username: username,
- email: email,
- groupId: groupId,
- customParameters: customParameters,
- );
- }
+ }) async =>
+ LiveChatPlatform.instance.openChatWindow(
+ licenseId: licenseId,
+ username: username,
+ email: email,
+ groupId: groupId,
+ customParameters: customParameters,
+ );
- Future closeChatWindow() async {
- return LiveChatPlatform.instance.closeChatWindow();
- }
+ /// Call to close/hide the chat window.
+ Future closeChatWindow() async =>
+ LiveChatPlatform.instance.closeChatWindow();
- Future clearChatSession() async {
- return LiveChatPlatform.instance.clearChatSession();
- }
+ /// Call to clear the chat session, for example, after logout,
+ Future clearChatSession() async =>
+ LiveChatPlatform.instance.clearChatSession();
+ /// Subscribe to events stream coming from live chat windows such as:
+ /// open, close, message, actual message text, etc.
Stream? get onLiveChatEventReceived =>
LiveChatPlatform.instance.getLiveChatEventsStream();
}
diff --git a/lib/src/live_chat_method_channel.dart b/lib/src/live_chat_method_channel.dart
index 2adcc64..e34576c 100644
--- a/lib/src/live_chat_method_channel.dart
+++ b/lib/src/live_chat_method_channel.dart
@@ -18,31 +18,27 @@ class MethodChannelLiveChat extends LiveChatPlatform {
required String email,
String? groupId,
Map? customParameters,
- }) {
- return _methodChannel.invokeMethod(
- openChatWindowKey,
- {
- licenseIdKey: licenseId,
- visitorNameKey: username,
- visitorEmailKey: email,
- groupIdKey: groupId,
- customParamsKey: customParameters,
- },
- );
- }
+ }) =>
+ _methodChannel.invokeMethod(
+ openChatWindowKey,
+ {
+ licenseIdKey: licenseId,
+ visitorNameKey: username,
+ visitorEmailKey: email,
+ groupIdKey: groupId,
+ customParamsKey: customParameters,
+ },
+ );
@override
- Future closeChatWindow() async {
- return _methodChannel.invokeMethod(closeChatWindowKey);
- }
+ Future closeChatWindow() async =>
+ _methodChannel.invokeMethod(closeChatWindowKey);
@override
- Future clearChatSession() async {
- return _methodChannel.invokeMethod(clearChatSessionKey);
- }
+ Future clearChatSession() async =>
+ _methodChannel.invokeMethod(clearChatSessionKey);
@override
- Stream? getLiveChatEventsStream() {
- return _eventsChannel.receiveBroadcastStream();
- }
+ Stream? getLiveChatEventsStream() =>
+ _eventsChannel.receiveBroadcastStream();
}
diff --git a/lib/src/live_chat_platform_interface.dart b/lib/src/live_chat_platform_interface.dart
index 3ffc294..d179720 100644
--- a/lib/src/live_chat_platform_interface.dart
+++ b/lib/src/live_chat_platform_interface.dart
@@ -1,7 +1,9 @@
import 'package:live_chat_plus/src/live_chat_method_channel.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
+/// LiveChatPlatform contract.
abstract class LiveChatPlatform extends PlatformInterface {
+ /// Constructs the contract.
LiveChatPlatform() : super(token: _token);
static final Object _token = Object();
@@ -21,6 +23,7 @@ abstract class LiveChatPlatform extends PlatformInterface {
_instance = instance;
}
+ /// Open the chat window.
Future openChatWindow({
required String licenseId,
required String username,
@@ -31,15 +34,19 @@ abstract class LiveChatPlatform extends PlatformInterface {
throw UnimplementedError('openChatWindow() has not been implemented.');
}
+ /// Close the chat window.
Future closeChatWindow() {
throw UnimplementedError('closeChatWindow() has not been implemented.');
}
+ /// Clea the chat session.
Future clearChatSession() {
throw UnimplementedError('clearChatSession() has not been implemented.');
}
+ /// Get the live chat events stream.
Stream? getLiveChatEventsStream() {
- throw UnimplementedError('getLiveChatEventsStream() has not been implemented.');
+ throw UnimplementedError(
+ 'getLiveChatEventsStream() has not been implemented.');
}
}
diff --git a/pubspec.yaml b/pubspec.yaml
index f35e054..945057b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: live_chat_plus
-description: "A Flutter plugin to bring LiveChat functionality to Flutter"
-version: 1.0.4
+description: "A Flutter plugin to bring LiveChat functionality to Flutter. It wraps chat-window android and ios SDKs, in addition to support for web"
+version: 1.0.5
repository: https://github.com/deriv-com/live-chat
issue_tracker: https://github.com/deriv-com/live-chat/issues
homepage: https://github.com/deriv-com/live-chat
@@ -14,7 +14,7 @@ dependencies:
sdk: flutter
flutter_web_plugins:
sdk: flutter
- js: ^0.6.3
+ js: ^0.7.1
plugin_platform_interface: ^2.1.8
dev_dependencies:
@@ -23,6 +23,9 @@ dev_dependencies:
flutter_lints: ^4.0.0
flutter:
+ assets:
+ - assets/live_chat.js
+
plugin:
platforms:
android:
@@ -33,3 +36,4 @@ flutter:
web:
pluginClass: LiveChatWeb
fileName: _internal/live_chat_web.dart
+