From 63bdceb2a8ef2d2823c07240db19ee6091dc4a25 Mon Sep 17 00:00:00 2001 From: Deepak Goyal Date: Tue, 20 Feb 2024 23:58:42 +0530 Subject: [PATCH] Migrate to js_interop (#407) --- intercom_flutter_web/CHANGELOG.md | 4 + .../lib/intercom_flutter_web.dart | 170 +++++++++--------- intercom_flutter_web/pubspec.yaml | 5 +- 3 files changed, 90 insertions(+), 89 deletions(-) diff --git a/intercom_flutter_web/CHANGELOG.md b/intercom_flutter_web/CHANGELOG.md index 9922958..7f3d7e6 100755 --- a/intercom_flutter_web/CHANGELOG.md +++ b/intercom_flutter_web/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.1.0 + +* Migrated to js_interop to be compatible with WASM. + ## 1.0.2 * Automatically Injected Intercom script, if it is not added. diff --git a/intercom_flutter_web/lib/intercom_flutter_web.dart b/intercom_flutter_web/lib/intercom_flutter_web.dart index 9e023a8..e5916c7 100644 --- a/intercom_flutter_web/lib/intercom_flutter_web.dart +++ b/intercom_flutter_web/lib/intercom_flutter_web.dart @@ -1,12 +1,12 @@ import 'dart:async'; -import 'dart:convert'; -import 'dart:html'; -import 'dart:js' as js; +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:intercom_flutter_platform_interface/intercom_flutter_platform_interface.dart'; import 'package:intercom_flutter_platform_interface/intercom_status_callback.dart'; import 'package:uuid/uuid.dart'; +import 'package:web/web.dart' as web; /// export the enum [IntercomVisibility] export 'package:intercom_flutter_platform_interface/intercom_flutter_platform_interface.dart' @@ -28,12 +28,13 @@ class IntercomFlutterWeb extends IntercomFlutterPlatform { StreamController _unreadController = StreamController.broadcast(); _unreadController.onListen = () { - js.context.callMethod('Intercom', [ - 'onUnreadCountChange', - js.allowInterop((unreadCount) { + globalContext.callMethod( + 'Intercom'.toJS, + 'onUnreadCountChange'.toJS, + ((JSAny unreadCount) { _unreadController.add(unreadCount); - }), - ]); + }).toJS, + ); }; return _unreadController.stream; } @@ -44,35 +45,36 @@ class IntercomFlutterWeb extends IntercomFlutterPlatform { String? androidApiKey, String? iosApiKey, }) async { - if (js.context['Intercom'] == null) { + if (globalContext.getProperty('Intercom'.toJS) == null) { // Intercom script is not added yet // Inject it from here in the body - var script = ScriptElement(); + web.HTMLScriptElement script = + web.document.createElement("script") as web.HTMLScriptElement; script.text = """ - window.intercomSettings = ${convertJsObjectToDartObject(updateIntercomSettings('app_id', "'$appId'"))}; + window.intercomSettings = ${updateIntercomSettings('app_id', "'$appId'").dartify()}; (function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/' + '$appId';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})(); """; - if (document.body != null) { - document.body!.append(script); + if (web.document.body != null) { + web.document.body!.appendChild(script); } } else { // boot the Intercom - await js.context.callMethod('Intercom', [ - 'boot', - convertJsObjectToDartObject(updateIntercomSettings('app_id', appId)), - ]); + globalContext.callMethod( + 'Intercom'.toJS, + 'boot'.toJS, + updateIntercomSettings('app_id', appId), + ); } print("initialized"); } @override Future setUserHash(String userHash) async { - await js.context.callMethod('Intercom', [ - 'update', - js.JsObject.jsify({ - 'user_hash': userHash, - }), - ]); + globalContext.callMethod( + 'Intercom'.toJS, + 'update'.toJS, + {'user_hash': userHash}.jsify(), + ); print("user hash added"); } @@ -88,23 +90,21 @@ class IntercomFlutterWeb extends IntercomFlutterPlatform { 'The parameter `email` must be null if `userId` is provided.'); } // register the user with userId - await js.context.callMethod('Intercom', [ - 'update', - js.JsObject.jsify({ - 'user_id': userId, - }), - ]); - // send the success callback only as web doesnot support the statusCallback. + globalContext.callMethod( + 'Intercom'.toJS, + 'update'.toJS, + {'user_id': userId}.jsify(), + ); + // send the success callback only as web does not support the statusCallback. statusCallback?.onSuccess?.call(); } else if (email?.isNotEmpty ?? false) { // register the user with email - await js.context.callMethod('Intercom', [ - 'update', - js.JsObject.jsify({ - 'email': email, - }), - ]); - // send the success callback only as web doesnot support the statusCallback. + globalContext.callMethod( + 'Intercom'.toJS, + 'update'.toJS, + {'email': email}.jsify(), + ); + // send the success callback only as web does not support the statusCallback. statusCallback?.onSuccess?.call(); } else { throw ArgumentError( @@ -117,13 +117,12 @@ class IntercomFlutterWeb extends IntercomFlutterPlatform { {IntercomStatusCallback? statusCallback}) async { // to register an unidentified user, a unique id will be created using the package uuid String userId = Uuid().v1(); - await js.context.callMethod('Intercom', [ - 'update', - js.JsObject.jsify({ - 'user_id': userId, - }), - ]); - // send the success callback only as web doesnot support the statusCallback. + globalContext.callMethod( + 'Intercom'.toJS, + 'update'.toJS, + {'user_id': userId}.jsify(), + ); + // send the success callback only as web does not support the statusCallback. statusCallback?.onSuccess?.call(); } @@ -180,130 +179,127 @@ class IntercomFlutterWeb extends IntercomFlutterPlatform { userAttributes['language_override'] = language; } - await js.context.callMethod('Intercom', [ - 'update', - js.JsObject.jsify(userAttributes), - ]); - // send the success callback only as web doesnot support the statusCallback. + globalContext.callMethod( + 'Intercom'.toJS, 'update'.toJS, userAttributes.jsify()); + // send the success callback only as web does not support the statusCallback. statusCallback?.onSuccess?.call(); } @override Future logEvent(String name, [Map? metaData]) async { - await js.context.callMethod('Intercom', [ - 'trackEvent', - name, - metaData != null ? js.JsObject.jsify(metaData) : null, - ]); + globalContext.callMethod( + 'Intercom'.toJS, + 'trackEvent'.toJS, + name.toJS, + metaData != null ? metaData.jsify() : null, + ); print("Logged event"); } @override Future setLauncherVisibility(IntercomVisibility visibility) async { - await js.context.callMethod('Intercom', [ - 'update', - convertJsObjectToDartObject(updateIntercomSettings( + globalContext.callMethod( + 'Intercom'.toJS, + 'update'.toJS, + updateIntercomSettings( 'hide_default_launcher', visibility == IntercomVisibility.visible ? false : true, - )), - ]); + ), + ); print("Showing launcher: $visibility"); } @override Future logout() async { - await js.context.callMethod('Intercom', ['shutdown']); + globalContext.callMethod('Intercom'.toJS, 'shutdown'.toJS); print("logout"); } @override Future displayMessenger() async { - await js.context.callMethod('Intercom', ['show']); + globalContext.callMethod('Intercom'.toJS, 'show'.toJS); print("Launched"); } @override Future hideMessenger() async { - await js.context.callMethod('Intercom', ['hide']); + globalContext.callMethod('Intercom'.toJS, 'hide'.toJS); print("Hidden"); } @override Future displayHelpCenter() async { - await js.context.callMethod('Intercom', ['showSpace', 'help']); + globalContext.callMethod('Intercom'.toJS, 'showSpace'.toJS, 'help'.toJS); print("Launched the Help Center"); } @override Future displayMessageComposer(String message) async { - await js.context.callMethod('Intercom', ['showNewMessage', message]); + globalContext.callMethod( + 'Intercom'.toJS, 'showNewMessage'.toJS, message.toJS); print("Message composer displayed"); } @override Future displayMessages() async { - await js.context.callMethod('Intercom', ['showMessages']); + globalContext.callMethod('Intercom'.toJS, 'showMessages'.toJS); print("Launched the Messenger with the message list"); } @override Future setBottomPadding(int padding) async { - await js.context.callMethod('Intercom', [ - 'update', - convertJsObjectToDartObject(updateIntercomSettings( + globalContext.callMethod( + 'Intercom'.toJS, + 'update'.toJS, + updateIntercomSettings( 'vertical_padding', padding, - )) - ]); + ), + ); print("Bottom padding set"); } @override Future displayArticle(String articleId) async { - await js.context.callMethod('Intercom', ['showArticle', articleId]); + globalContext.callMethod( + 'Intercom'.toJS, 'showArticle'.toJS, articleId.toJS); } @override Future displaySurvey(String surveyId) async { - await js.context.callMethod('Intercom', ['startSurvey', surveyId]); + globalContext.callMethod( + 'Intercom'.toJS, 'startSurvey'.toJS, surveyId.toJS); } @override Future displayConversation(String conversationId) async { - await js.context - .callMethod('Intercom', ['showConversation', conversationId]); + globalContext.callMethod( + 'Intercom'.toJS, 'showConversation'.toJS, conversationId.toJS); } @override Future displayTickets() async { - await js.context.callMethod('Intercom', ['showSpace', 'tickets']); + globalContext.callMethod('Intercom'.toJS, 'showSpace'.toJS, 'tickets'.toJS); print("Launched Tickets space"); } /// get the [window.IntercomSettings] - js.JsObject getIntercomSettings() { - if (js.context.hasProperty('intercomSettings')) { - return js.JsObject.fromBrowserObject(js.context['intercomSettings']); + JSObject getIntercomSettings() { + if (globalContext.hasProperty('intercomSettings'.toJS).toDart) { + return globalContext.getProperty('intercomSettings'.toJS) as JSObject; } - return js.JsObject.jsify({}); + return JSObject(); } /// add/update property to [window.IntercomSettings] /// and returns the updated object - js.JsObject updateIntercomSettings(String key, dynamic value) { + JSObject updateIntercomSettings(String key, dynamic value) { var intercomSettings = getIntercomSettings(); intercomSettings[key] = value; return intercomSettings; } - - /// convert the [js.JsObject] to [Map] - Object convertJsObjectToDartObject(js.JsObject jsObject) { - return json.decode(js.context["JSON"].callMethod("stringify", [ - jsObject, - ])); - } } diff --git a/intercom_flutter_web/pubspec.yaml b/intercom_flutter_web/pubspec.yaml index a342723..865af68 100644 --- a/intercom_flutter_web/pubspec.yaml +++ b/intercom_flutter_web/pubspec.yaml @@ -1,6 +1,6 @@ name: intercom_flutter_web description: Web platform implementation of intercom_flutter -version: 1.0.2 +version: 1.1.0 homepage: https://github.com/v3rm0n/intercom_flutter flutter: @@ -17,6 +17,7 @@ dependencies: sdk: flutter intercom_flutter_platform_interface: ^2.0.0 uuid: ^4.2.1 # to get the random uuid for loginUnidentifiedUser in web + web: '>=0.3.0 <0.6.0' dev_dependencies: flutter_test: @@ -24,5 +25,5 @@ dev_dependencies: mockito: ^5.4.0 environment: - sdk: ">=3.0.0 <4.0.0" + sdk: ">=3.2.0 <4.0.0" flutter: ">=3.10.0" \ No newline at end of file