Skip to content

Commit a6eb429

Browse files
committed
Migrate dart:html to package:web to support WASM.
1 parent a14d4f9 commit a6eb429

File tree

4 files changed

+78
-44
lines changed

4 files changed

+78
-44
lines changed

example/pubspec.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ description: Demonstrates how to use the flutter_unity_widget plugin.
66
publish_to: "none" # Remove this line if you wish to publish to pub.dev
77

88
environment:
9-
sdk: ">=2.12.0 <4.0.0"
9+
sdk: ">=2.17.0 <4.0.0"
10+
# >=2.17 or higher is needed for pointer_interceptor to work on web with WASM.
11+
1012

1113
dependencies:
1214
cupertino_icons: ^1.0.0
1315
flutter:
1416
sdk: flutter
1517
flutter_unity_widget:
1618
path: ../
17-
pointer_interceptor: ^0.9.3+2
19+
pointer_interceptor: ^0.10.0
1820

1921
dev_dependencies:
2022
flutter_test:

lib/flutter_unity_widget.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ library flutter_unity_widget;
33
export 'src/facade_controller.dart';
44
export 'src/facade_widget.dart'
55
if (dart.library.io) 'src/io/unity_widget.dart'
6-
if (dart.library.html) 'src/web/unity_widget.dart';
6+
if (dart.library.js_interop) 'src/web/unity_widget.dart';
77
export 'src/helpers/events.dart';
88
export 'src/helpers/misc.dart';
99
export 'src/helpers/types.dart';

lib/src/web/web_unity_widget_controller.dart

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import 'dart:developer';
22
import 'dart:async';
33
import 'dart:convert';
4-
import 'dart:html' as html;
4+
import 'dart:js_interop';
55

6+
import 'package:web/web.dart' as web;
67
import 'package:flutter/foundation.dart';
78
import 'package:flutter/services.dart';
89
import '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+
2631
class 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
}

pubspec.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ version: 2022.2.1
88
homepage: https://github.com/juicycleff/flutter-unity-view-widget/tree/master
99

1010
environment:
11-
sdk: ">=2.16.0 <4.0.0"
12-
flutter: ">=3.3.0"
11+
sdk: ">=3.2.0 <4.0.0"
12+
flutter: ">=3.16.0"
1313

1414
dependencies:
1515
flutter:
@@ -21,6 +21,7 @@ dependencies:
2121
plugin_platform_interface: ^2.1.2
2222
webview_flutter: ^4.0.0
2323
webview_flutter_web: ^0.2.2
24+
web: '>=0.3.0 <2.0.0' # Needs to resolve to >=0.5.0 to use WebAssembly (WASM).
2425
# ffi: ^1.2.1 // required for windows support
2526

2627
dev_dependencies:

0 commit comments

Comments
 (0)