Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 777d15f

Browse files
committed
[web] Support platform view creation params
1 parent 23b0431 commit 777d15f

4 files changed

Lines changed: 89 additions & 27 deletions

File tree

lib/web_ui/lib/src/engine/platform_views/content_manager.dart

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,14 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;
6+
57
import '../browser_detection.dart';
68
import '../dom.dart';
79
import '../embedder.dart';
810
import '../util.dart';
911
import 'slots.dart';
1012

11-
/// A function which takes a unique `id` and some `params` and creates an HTML element.
12-
///
13-
/// This is made available to end-users through dart:ui in web.
14-
typedef ParameterizedPlatformViewFactory = DomElement Function(
15-
int viewId, {
16-
Object? params,
17-
});
18-
19-
/// A function which takes a unique `id` and creates an HTML element.
20-
///
21-
/// This is made available to end-users through dart:ui in web.
22-
typedef PlatformViewFactory = DomElement Function(int viewId);
23-
2413
/// This class handles the lifecycle of Platform Views in the DOM of a Flutter Web App.
2514
///
2615
/// There are three important parts of Platform Views. This class manages two of
@@ -68,8 +57,8 @@ class PlatformViewManager {
6857
/// `factoryFunction` needs to be a [PlatformViewFactory].
6958
bool registerFactory(String viewType, Function factoryFunction,
7059
{bool isVisible = true}) {
71-
assert(factoryFunction is PlatformViewFactory ||
72-
factoryFunction is ParameterizedPlatformViewFactory);
60+
assert(factoryFunction is ui_web.PlatformViewFactory ||
61+
factoryFunction is ui_web.ParameterizedPlatformViewFactory);
7362

7463
if (_factories.containsKey(viewType)) {
7564
return false;
@@ -121,10 +110,11 @@ class PlatformViewManager {
121110
final Function factoryFunction = _factories[viewType]!;
122111
late DomElement content;
123112

124-
if (factoryFunction is ParameterizedPlatformViewFactory) {
125-
content = factoryFunction(viewId, params: params);
113+
if (factoryFunction is ui_web.ParameterizedPlatformViewFactory) {
114+
content = factoryFunction(viewId, params: params) as DomElement;
126115
} else {
127-
content = (factoryFunction as PlatformViewFactory).call(viewId);
116+
factoryFunction as ui_web.PlatformViewFactory;
117+
content = factoryFunction(viewId) as DomElement;
128118
}
129119

130120
_ensureContentCorrectlySized(content, viewType);

lib/web_ui/lib/src/engine/platform_views/message_handler.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class PlatformViewMessageHandler {
6868
final Map<dynamic, dynamic> args = methodCall.arguments as Map<dynamic, dynamic>;
6969
final int viewId = args.readInt('id');
7070
final String viewType = args.readString('viewType');
71+
final Object? params = args['params'];
7172

7273
if (!_contentManager.knowsViewType(viewType)) {
7374
callback(_codec.encodeErrorEnvelope(
@@ -89,11 +90,10 @@ class PlatformViewMessageHandler {
8990
return;
9091
}
9192

92-
// TODO(hterkelsen): How can users add extra `args` from the HtmlElementView widget?
9393
final DomElement content = _contentManager.renderContent(
9494
viewType,
9595
viewId,
96-
args,
96+
params,
9797
);
9898

9999
// For now, we don't need anything fancier. If needed, this can be converted

lib/web_ui/lib/ui_web/src/ui_web/platform_view_registry.dart

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,32 @@
44

55
import 'package:ui/src/engine.dart';
66

7+
/// A function which takes a unique `id` and some `params` and creates an HTML
8+
/// element.
9+
typedef ParameterizedPlatformViewFactory = Object Function(
10+
int viewId, {
11+
Object? params,
12+
});
13+
14+
/// A function which takes a unique `id` and creates an HTML element.
15+
typedef PlatformViewFactory = Object Function(int viewId);
16+
717
/// The platform view registry for this app.
818
final PlatformViewRegistry platformViewRegistry = PlatformViewRegistry();
919

1020
/// A registry for factories that create platform views.
1121
class PlatformViewRegistry {
12-
/// Register [viewTypeId] as being creating by the given [viewFactory].
13-
/// [viewFactory] can be any function that takes an integer and returns an
14-
/// `HTMLElement` DOM object.
22+
/// Register [viewType] as being created by the given [viewFactory].
23+
///
24+
/// [viewFactory] can be any function that takes an integer and optional
25+
/// `params` and returns an `HTMLElement` DOM object.
1526
bool registerViewFactory(
16-
String viewTypeId,
17-
Object Function(int viewId) viewFactory, {
27+
String viewType,
28+
Function viewFactory, {
1829
bool isVisible = true,
1930
}) {
2031
return platformViewManager.registerFactory(
21-
viewTypeId,
32+
viewType,
2233
viewFactory,
2334
isVisible: isVisible,
2435
);

lib/web_ui/test/engine/platform_views/message_handler_test.dart

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ void main() {
1515

1616
const MethodCodec codec = StandardMethodCodec();
1717

18+
typedef PlatformViewFactoryCall = ({int viewId, Object? params});
19+
1820
void testMain() {
1921
group('PlatformViewMessageHandler', () {
2022
group('handlePlatformViewCall', () {
@@ -109,6 +111,64 @@ void testMain() {
109111
reason:
110112
'The response should be a success envelope, with null in it.');
111113
});
114+
115+
test('passes creation params to the factory', () async {
116+
final List<PlatformViewFactoryCall> factoryCalls = <PlatformViewFactoryCall>[];
117+
contentManager.registerFactory(viewType, (int viewId, {Object? params}) {
118+
factoryCalls.add((viewId: viewId, params: params));
119+
return createDomHTMLDivElement();
120+
});
121+
final PlatformViewMessageHandler messageHandler = PlatformViewMessageHandler(
122+
contentManager: contentManager,
123+
);
124+
125+
final List<Completer<ByteData?>> completers = <Completer<ByteData?>>[];
126+
127+
completers.add(Completer<ByteData?>());
128+
messageHandler.handlePlatformViewCall(
129+
_getCreateMessage(viewType, 111),
130+
completers.last.complete,
131+
);
132+
133+
completers.add(Completer<ByteData?>());
134+
messageHandler.handlePlatformViewCall(
135+
_getCreateMessage(viewType, 222, <dynamic, dynamic>{'foo': 'bar'}),
136+
completers.last.complete,
137+
);
138+
139+
final List<ByteData?> responses = await Future.wait(
140+
completers.map((Completer<ByteData?> c) => c.future),
141+
);
142+
143+
for (final ByteData? response in responses) {
144+
expect(
145+
codec.decodeEnvelope(response!),
146+
isNull,
147+
reason: 'The response should be a success envelope, with null in it.',
148+
);
149+
}
150+
151+
expect(factoryCalls, hasLength(2));
152+
expect(factoryCalls[0].viewId, 111);
153+
expect(factoryCalls[0].params, isNull);
154+
expect(factoryCalls[1].viewId, 222);
155+
expect(factoryCalls[1].params, <dynamic, dynamic>{'foo': 'bar'});
156+
});
157+
158+
test('fails if the factory returns a non-DOM object', () async {
159+
contentManager.registerFactory(viewType, (int viewId) {
160+
// Return an object that's not a DOM element.
161+
return Object();
162+
});
163+
164+
final PlatformViewMessageHandler messageHandler =
165+
PlatformViewMessageHandler(contentManager: contentManager);
166+
final ByteData? message = _getCreateMessage(viewType, viewId);
167+
168+
expect(() {
169+
messageHandler.handlePlatformViewCall(message, (_) {});
170+
}, throwsA(isA<TypeError>()));
171+
});
112172
});
113173

114174
group('"dispose" message', () {
@@ -162,12 +222,13 @@ class _FakePlatformViewManager extends PlatformViewManager {
162222
}
163223
}
164224

165-
ByteData? _getCreateMessage(String viewType, int viewId) {
225+
ByteData? _getCreateMessage(String viewType, int viewId, [Object? params]) {
166226
return codec.encodeMethodCall(MethodCall(
167227
'create',
168228
<String, dynamic>{
169229
'id': viewId,
170230
'viewType': viewType,
231+
if (params != null) 'params': params,
171232
},
172233
));
173234
}

0 commit comments

Comments
 (0)