1
1
import 'dart:developer' ;
2
2
import 'dart:async' ;
3
3
import 'dart:convert' ;
4
- import 'dart:html' as html ;
4
+ import 'dart:js_interop' ;
5
5
6
+ import 'package:web/web.dart' as web;
6
7
import 'package:flutter/foundation.dart' ;
7
8
import 'package:flutter/services.dart' ;
8
9
import 'package:flutter_web_plugins/flutter_web_plugins.dart' ;
@@ -23,13 +24,16 @@ class UnityWebEvent {
23
24
final dynamic data;
24
25
}
25
26
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
+
26
31
class WebUnityWidgetController extends UnityWidgetController {
27
32
final WebUnityWidgetState _unityWidgetState;
28
33
29
34
static Registrar ? webRegistrar;
30
35
31
- late html.MessageEvent _unityFlutterBiding;
32
- late html.MessageEvent _unityFlutterBidingFn;
36
+ late JSFunction _messageListener;
33
37
34
38
bool unityReady = false ;
35
39
bool unityPause = true ;
@@ -99,27 +103,52 @@ class WebUnityWidgetController extends UnityWidgetController {
99
103
100
104
_registerEvents () {
101
105
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
+ }
121
149
}
122
- });
150
+ }).toJS;
151
+ web.window.addEventListener ('message' , _messageListener);
123
152
}
124
153
}
125
154
@@ -189,11 +218,13 @@ class WebUnityWidgetController extends UnityWidgetController {
189
218
190
219
void callUnityFn ({required String fnName}) {
191
220
if (kIsWeb) {
192
- _unityFlutterBidingFn = html .MessageEvent (
221
+ final web. MessageEvent _unityFlutterBidingFn = web .MessageEvent (
193
222
'unityFlutterBidingFnCal' ,
194
- data: fnName,
223
+ web.MessageEventInit (
224
+ data: fnName.toJS,
225
+ ),
195
226
);
196
- html .window.dispatchEvent (_unityFlutterBidingFn);
227
+ web .window.dispatchEvent (_unityFlutterBidingFn);
197
228
}
198
229
}
199
230
@@ -203,27 +234,29 @@ class WebUnityWidgetController extends UnityWidgetController {
203
234
required String message,
204
235
}) {
205
236
if (kIsWeb) {
206
- _unityFlutterBiding = html .MessageEvent (
237
+ final web. MessageEvent _unityFlutterBiding = web .MessageEvent (
207
238
'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
+ ),
213
246
);
214
- html .window.dispatchEvent (_unityFlutterBiding);
247
+ web .window.dispatchEvent (_unityFlutterBiding);
215
248
postProcess ();
216
249
}
217
250
}
218
251
219
252
/// This method makes sure Unity has been refreshed and is ready to receive further messages.
220
253
void postProcess () {
221
- html .Element ? frame = html .document
254
+ web .Element ? frame = web.window .document
222
255
.querySelector ('flt-platform-view' )
223
256
? .querySelector ('iframe' );
224
257
225
- if (frame != null ) {
226
- ( frame as html. IFrameElement ) .focus ();
258
+ if (frame != null && frame is web. HTMLIFrameElement ) {
259
+ frame.focus ();
227
260
}
228
261
}
229
262
@@ -292,9 +325,7 @@ class WebUnityWidgetController extends UnityWidgetController {
292
325
void dispose () {
293
326
_cancelSubscriptions ();
294
327
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);
298
329
}
299
330
}
300
331
}
0 commit comments