11import 'dart:developer' ;
22import 'dart:async' ;
33import 'dart:convert' ;
4- import 'dart:html' as html ;
4+ import 'dart:js_interop' ;
55
6+ import 'package:web/web.dart' as web;
67import 'package:flutter/foundation.dart' ;
78import 'package:flutter/services.dart' ;
89import 'package:flutter_web_plugins/flutter_web_plugins.dart' ;
@@ -23,13 +24,16 @@ class UnityWebEvent {
2324 final dynamic data;
2425}
2526
27+ // use JSON.stringify to turn JS objects into strings which we can json decode.
28+ @JS ('JSON.stringify' )
29+ external JSString jsonStringify (JSAny value);
30+
2631class WebUnityWidgetController extends UnityWidgetController {
2732 final WebUnityWidgetState _unityWidgetState;
2833
2934 static Registrar ? webRegistrar;
3035
31- late html.MessageEvent _unityFlutterBiding;
32- late html.MessageEvent _unityFlutterBidingFn;
36+ late JSFunction _messageListener;
3337
3438 bool unityReady = false ;
3539 bool unityPause = true ;
@@ -99,27 +103,52 @@ class WebUnityWidgetController extends UnityWidgetController {
99103
100104 _registerEvents () {
101105 if (kIsWeb) {
102- html.window.addEventListener ('message' , (event) {
103- final raw = (event as html.MessageEvent ).data.toString ();
104- // ignore: unnecessary_null_comparison
105- if (raw == '' || raw == null ) return ;
106- if (raw == 'unityReady' ) {
107- unityReady = true ;
108- unityPause = false ;
109-
110- _unityStreamController.add (UnityCreatedEvent (0 , {}));
111- return ;
112- }
113-
114- try {
115- _processEvents (UnityWebEvent (
116- name: event.data['name' ],
117- data: event.data['data' ],
118- ));
119- } catch (e) {
120- log ('Unexpected format' , error: e);
106+ _messageListener = ((web.Event event) {
107+ if (event is web.MessageEvent ) {
108+ final jsData = event.data;
109+ String data = "" ;
110+
111+ // Handle a raw JS Object [Object object] instead of a json string.
112+ if (jsData is JSObject ) {
113+ try {
114+ data = jsonStringify (jsData).toDart;
115+ } catch (e) {
116+ log ('Failed to stringify JS object' , error: e);
117+ return ;
118+ }
119+ }
120+ // this can be either a raw string like "unityReady" or a json string "{\"name\":\"\", ..}"
121+ else if (jsData is JSString ) {
122+ data = jsData.toDart;
123+ }
124+
125+ if (data.isNotEmpty) {
126+ if (data == 'unityReady' ) {
127+ unityReady = true ;
128+ unityPause = false ;
129+ _unityStreamController.add (UnityCreatedEvent (0 , {}));
130+ return ;
131+ } else {
132+ try {
133+ final decoded = json.decode (data);
134+ if (decoded is Map <String , dynamic > &&
135+ decoded.containsKey ("name" ) &&
136+ decoded.containsKey ("data" )) {
137+ _processEvents (UnityWebEvent (
138+ name: decoded['name' ],
139+ data: decoded['data' ],
140+ ));
141+ } else {
142+ log ('Unexpected json object' , error: data);
143+ }
144+ } catch (e) {
145+ log ('Unexpected json object' , error: e);
146+ }
147+ }
148+ }
121149 }
122- });
150+ }).toJS;
151+ web.window.addEventListener ('message' , _messageListener);
123152 }
124153 }
125154
@@ -189,11 +218,13 @@ class WebUnityWidgetController extends UnityWidgetController {
189218
190219 void callUnityFn ({required String fnName}) {
191220 if (kIsWeb) {
192- _unityFlutterBidingFn = html .MessageEvent (
221+ final web. MessageEvent _unityFlutterBidingFn = web .MessageEvent (
193222 'unityFlutterBidingFnCal' ,
194- data: fnName,
223+ web.MessageEventInit (
224+ data: fnName.toJS,
225+ ),
195226 );
196- html .window.dispatchEvent (_unityFlutterBidingFn);
227+ web .window.dispatchEvent (_unityFlutterBidingFn);
197228 }
198229 }
199230
@@ -203,27 +234,29 @@ class WebUnityWidgetController extends UnityWidgetController {
203234 required String message,
204235 }) {
205236 if (kIsWeb) {
206- _unityFlutterBiding = html .MessageEvent (
237+ final web. MessageEvent _unityFlutterBiding = web .MessageEvent (
207238 'unityFlutterBiding' ,
208- data: json.encode ({
209- "gameObject" : gameObject,
210- "methodName" : methodName,
211- "message" : message,
212- }),
239+ web.MessageEventInit (
240+ data: json.encode ({
241+ "gameObject" : gameObject,
242+ "methodName" : methodName,
243+ "message" : message,
244+ }).toJS,
245+ ),
213246 );
214- html .window.dispatchEvent (_unityFlutterBiding);
247+ web .window.dispatchEvent (_unityFlutterBiding);
215248 postProcess ();
216249 }
217250 }
218251
219252 /// This method makes sure Unity has been refreshed and is ready to receive further messages.
220253 void postProcess () {
221- html .Element ? frame = html .document
254+ web .Element ? frame = web.window .document
222255 .querySelector ('flt-platform-view' )
223256 ? .querySelector ('iframe' );
224257
225- if (frame != null ) {
226- ( frame as html. IFrameElement ) .focus ();
258+ if (frame != null && frame is web. HTMLIFrameElement ) {
259+ frame.focus ();
227260 }
228261 }
229262
@@ -292,9 +325,7 @@ class WebUnityWidgetController extends UnityWidgetController {
292325 void dispose () {
293326 _cancelSubscriptions ();
294327 if (kIsWeb) {
295- html.window.removeEventListener ('message' , (_) {});
296- html.window.removeEventListener ('unityFlutterBiding' , (event) {});
297- html.window.removeEventListener ('unityFlutterBidingFnCal' , (event) {});
328+ web.window.removeEventListener ('message' , _messageListener);
298329 }
299330 }
300331}
0 commit comments