Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/support flutter widget #904

Merged
merged 81 commits into from
Dec 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
b3787db
:sparkles: feat: buildOwner should use the owner of context.
answershuto Nov 24, 2021
47278a4
:sparkles: feat: add buildOwner to kraken of main.
answershuto Nov 24, 2021
b6e8a9d
:art: chore: buildOwner should be final.
answershuto Nov 24, 2021
47ad64d
chore: move widget implets into folder.
andycall Nov 24, 2021
3f371fe
feat: add krakenRenderObject adaptor to support wrap Widgets into kra…
andycall Nov 24, 2021
97358f5
:sparkles: feat: add children to kraken widget adapter.
answershuto Nov 24, 2021
2b04a69
:sparkles: feat: modify _KrakenAdapterWidgetPropertiesState to _Krake…
answershuto Nov 24, 2021
64cc50f
:sparkles: feat: convert list of dom.Element to Widget.
answershuto Nov 24, 2021
27da225
:sparkles: feat: add removechild to WidgetElement.
answershuto Nov 24, 2021
996a95d
:sparkles: feat: del child.
answershuto Nov 24, 2021
dde4e6e
feat: add element adaptor.
andycall Nov 24, 2021
801ca17
:art: chore: remove invalid code.
answershuto Nov 25, 2021
1dbae39
:sparkles: feat: add convertNodeListToWidgetList.
answershuto Nov 25, 2021
50a5079
chore: remove missing api.
andycall Nov 25, 2021
51bc1aa
feat: KrakenLeafRenderObjectWidget --> KrakenElementToWidgetAdaptor.
andycall Nov 25, 2021
3d75398
:sparkles: feat: needs to set parent KrakenRenderObjectToWidgetElemen…
answershuto Nov 25, 2021
cf438c9
:art: chore: remove _element.
answershuto Nov 25, 2021
66b73c5
:art: chore: remove todo of comment.
answershuto Nov 25, 2021
21ddca1
:bug: fix: removeChild should set childNodes to onChidrenChanged.
answershuto Nov 25, 2021
b5293eb
:art: chore: modify filename of widgets to widget.
answershuto Nov 26, 2021
8943ef3
:art: chore: add comment.
answershuto Nov 26, 2021
3580f58
:bug: fix: custom element should return widget of self when convertNo…
answershuto Nov 26, 2021
ed85d65
:bug: fix: _state and _widget should be init in construct of WidgetEl…
answershuto Nov 26, 2021
70c42d5
:sparkles: feat: flutter element should be umount when ro be detach.
answershuto Nov 26, 2021
22b55a7
:sparkles: feat: _detachWidget should from ancestor of widget.
answershuto Nov 26, 2021
febb560
:art: chore: modify detachToRenderTree to detachFromRenderTree.
answershuto Nov 29, 2021
7558910
:bug: fix: detachFromRenderTree should not create element.
answershuto Nov 29, 2021
33db783
:bug: fix: _detachWidget need not parent params.
answershuto Nov 29, 2021
22704a5
:sparkles: feat: should save adaptor for WidgetElement.
answershuto Nov 29, 2021
5f3d120
:art: chore: remove comment.
answershuto Nov 29, 2021
fd8d4ad
:bug: fix: if renderview is building,skip the buildScope phase.
answershuto Nov 30, 2021
df7d7d8
:art: chore: modify comment.
answershuto Nov 30, 2021
5f73f03
:art: chore: del print.
answershuto Nov 30, 2021
b164994
:bug: fix: remove isBuilding from controller.
answershuto Nov 30, 2021
4993eb1
:bug: fix: Nested widgets should be able to be mounted under nodes in…
answershuto Dec 1, 2021
2acd1c8
:art: chore: delete invalid code.
answershuto Dec 1, 2021
8b93fe6
:sparkles: feat: modify attachToRenderTree.
answershuto Dec 1, 2021
9b35f21
:bug: fix: remove detachFromTree, Element of Flutter should be unmoun…
answershuto Dec 1, 2021
1488526
:art: chore: delete element.
answershuto Dec 1, 2021
db815fc
:sparkles: feat: should find Flutter element by element when the elem…
answershuto Dec 2, 2021
abc4494
Merge branch 'main' into feat/support_flutter_widget
answershuto Dec 6, 2021
3f7657c
:sparkles: feat: Flutter Widget should not be a intrinsicBox.
answershuto Dec 6, 2021
64b5b92
:bug: fix: render object of KrakenElementToFlutterElementAdaptor shou…
answershuto Dec 6, 2021
23e0998
:bug: fix: elememnt should be disposeRenderObject whtn unmount.
answershuto Dec 6, 2021
3259e5b
Merge branch 'main' into feat/support_flutter_widget
answershuto Dec 7, 2021
8776dd8
:sparkles: feat: merge from main.
answershuto Dec 7, 2021
cfebe0b
:art: chore: modify tighten.
answershuto Dec 7, 2021
6b281a4
:art: chore: modify is!.
answershuto Dec 7, 2021
07cdb08
:art: chore: dealwith lint.
answershuto Dec 7, 2021
a99325d
:fire: chore: remove flag of mounted.
answershuto Dec 7, 2021
b07dc43
:sparkles: feat: custom element should attach to element of parent.
answershuto Dec 7, 2021
58898f2
:white_check_mark: test: modify test of integration.
answershuto Dec 7, 2021
b1b1f7b
Merge branch 'main' into feat/support_flutter_widget
answershuto Dec 13, 2021
b5d9555
:seedling: chore: add file.
answershuto Dec 14, 2021
efd8aa4
:zap: feat: ro of element should not be attach render tree when paren…
answershuto Dec 14, 2021
3dc70e7
:sparkles: featL feat: KrakenElementToFlutterElementAdaptor should be…
answershuto Dec 14, 2021
f522c49
Merge branch 'main' into feat/support_flutter_widget
answershuto Dec 14, 2021
cf8821d
:art: chore: deal with lint.
answershuto Dec 15, 2021
866c3df
:art: chore: del print.
answershuto Dec 15, 2021
17a9f6b
:art: chore: add comment.
answershuto Dec 15, 2021
cc4a670
:white_check_mark: test: add some custom element to test.
answershuto Dec 15, 2021
4e57a5f
:art: chore: del comment.
answershuto Dec 15, 2021
8161e10
:white_check_mark: test: add test for custom element.
answershuto Dec 15, 2021
2fd6fa7
:sparkles: feat: renderObjectElement should be found for attachToRend…
answershuto Dec 15, 2021
708e76c
:art: chore: del comment.
answershuto Dec 15, 2021
21d63bf
:white_check_mark: test: add test for custom element.
answershuto Dec 15, 2021
3210e89
:white_check_mark: test: modify main of custom element test.
answershuto Dec 15, 2021
382b129
:white_check_mark: test: add image.
answershuto Dec 15, 2021
0bd05c4
:white_check_mark: test: modify test.
answershuto Dec 15, 2021
75991f8
:white_check_mark: test: modify test of customelement.
answershuto Dec 17, 2021
f611ad9
Merge branch 'main' into feat/support_flutter_widget
answershuto Dec 17, 2021
29b0911
:art: chore: modify dir.
answershuto Dec 17, 2021
f9337e9
:art: chore: modify KrakenElement to rootFlutterElement.
answershuto Dec 17, 2021
15d425d
:art: chore: modify element of flutter in kraken to flutter element.
answershuto Dec 17, 2021
6395ed8
:art: chore: delete comment.
answershuto Dec 17, 2021
a5a12ef
:art: chore: add newline.
answershuto Dec 17, 2021
831bc12
:bug: fix: flexbox_margin-left ex-ref.
answershuto Dec 17, 2021
87371bf
:art: chore: merge main.
answershuto Dec 21, 2021
70e89ce
:art: chore: dealwith lint.
answershuto Dec 21, 2021
6cad69b
:sparkles: feat: cache flutter widget to node.
answershuto Dec 21, 2021
e02a71a
:sparkles: feat: add flutter widget to node.
answershuto Dec 21, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 72 additions & 19 deletions integration_tests/lib/custom/custom_element.dart
Original file line number Diff line number Diff line change
@@ -1,42 +1,79 @@
import 'dart:async';
import 'package:kraken/dom.dart';
import 'package:kraken/dom.dart' as dom;
import 'package:kraken/widget.dart';
import 'package:flutter/material.dart' show TextDirection, TextStyle, Color, Image, Text, AssetImage, Widget, BuildContext hide Element;
import 'package:waterfall_flow/waterfall_flow.dart';
import 'package:flutter/material.dart';

class WaterfallFlowWidgetElement extends WidgetElement {
WaterfallFlowWidgetElement(dom.EventTargetContext? context) :
super(context);

List<Widget> _children = [];

Widget _func (BuildContext context, int index) {
return _children[index];
}

@override
Widget build(BuildContext context, Map<String, dynamic> properties, List<Widget> children) {
_children = children;

return WaterfallFlow.builder(
itemBuilder: _func,
padding: EdgeInsets.all(5.0),
gridDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5.0,
lastChildLayoutTypeBuilder: (index) => index == children.length
? LastChildLayoutType.foot
: LastChildLayoutType.none,
),
);
}
}

class TextWidgetElement extends WidgetElement {
TextWidgetElement(EventTargetContext? context) :
TextWidgetElement(dom.EventTargetContext? context) :
super(context);

@override
Widget build(BuildContext context, Map<String, dynamic> properties) {
Widget build(BuildContext context, Map<String, dynamic> properties, List<Widget> children) {
return Text(properties['value'] ?? '', textDirection: TextDirection.ltr, style: TextStyle(color: Color.fromARGB(255, 100, 100, 100)));
}
}

class ImageWidgetElement extends WidgetElement {
ImageWidgetElement(EventTargetContext? context) :
ImageWidgetElement(dom.EventTargetContext? context) :
super(context);

@override
Widget build(BuildContext context, Map<String, dynamic> properties) {
Widget build(BuildContext context, Map<String, dynamic> properties, List<Widget> children) {
return Image(image: AssetImage(properties['src']));
}
}

void defineKrakenCustomElements() {
Kraken.defineCustomElement('sample-element', (EventTargetContext? context) {
return SampleElement(context);
});
Kraken.defineCustomElement('flutter-text', (EventTargetContext? context) {
return TextWidgetElement(context);
});
Kraken.defineCustomElement('flutter-asset-image', (EventTargetContext? context) {
return ImageWidgetElement(context);
});
class ContainerWidgetElement extends WidgetElement {
ContainerWidgetElement(dom.EventTargetContext? context) :
super(context);

@override
Widget build(BuildContext context, Map<String, dynamic> properties, List<Widget> children) {
return Container(
width: 200,
height: 200,
decoration: const BoxDecoration(
border: Border( top: BorderSide( width: 5, color: Colors.red ), bottom: BorderSide( width: 5, color: Colors.red ), left: BorderSide( width: 5, color: Colors.red ), right: BorderSide( width: 5, color: Colors.red )),
),
child: Column(
children: children,
),
);
}
}

class SampleElement extends Element {
SampleElement(EventTargetContext? context)
class SampleElement extends dom.Element {
SampleElement(dom.EventTargetContext? context)
: super(context);

@override
Expand Down Expand Up @@ -74,4 +111,20 @@ class SampleElement extends Element {
}
}


void defineKrakenCustomElements() {
Kraken.defineCustomElement('waterfall-flow', (dom.EventTargetContext? context) {
return WaterfallFlowWidgetElement(context);
});
Kraken.defineCustomElement('flutter-container', (dom.EventTargetContext? context) {
return ContainerWidgetElement(context);
});
Kraken.defineCustomElement('sample-element', (dom.EventTargetContext? context) {
return SampleElement(context);
});
Kraken.defineCustomElement('flutter-text', (dom.EventTargetContext? context) {
return TextWidgetElement(context);
});
Kraken.defineCustomElement('flutter-asset-image', (dom.EventTargetContext? context) {
return ImageWidgetElement(context);
});
}
1 change: 1 addition & 0 deletions integration_tests/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies:
kraken_video_player: ^2.0.0-dev.0
kraken_websocket: ^1.0.0
kraken_webview: ^2.0.0-dev.0
waterfall_flow: ^3.0.1

dev_dependencies:
flutter_test:
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
101 changes: 101 additions & 0 deletions integration_tests/specs/dom/elements/custom-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,107 @@ describe('custom widget element', () => {

simulateClick(20, 20);
});

it('text node should be child of flutter container', async () => {
const container = document.createElement('flutter-container');
const text = document.createTextNode('text');
document.body.appendChild(container);
container.appendChild(text);
await snapshot();
});

it('element should be child of flutter container', async () => {
const container = document.createElement('flutter-container');
const element = document.createElement('div');
element.style.width = '30px';
element.style.height = '30px';
element.style.backgroundColor = 'red';
container.appendChild(element);
document.body.appendChild(container);
await snapshot();
});

it('flutter widget should be child of flutter container', async () => {
const container = document.createElement('flutter-container');
const fluttetText = document.createElement('flutter-text');
fluttetText.setAttribute('value', 'text');
container.appendChild(fluttetText);
document.body.appendChild(container);

await snapshot();
});

it('flutter widget and dom node should be child of flutter container', async () => {
const container = document.createElement('flutter-container');
document.body.appendChild(container);

const element = document.createElement('div');
element.style.backgroundColor = 'red';
element.appendChild(document.createTextNode('div element'));
container.appendChild(element);

const fluttetText = document.createElement('flutter-text');
fluttetText.setAttribute('value', 'text');
container.appendChild(fluttetText);

const text = document.createTextNode('text');
container.appendChild(text);

await snapshot();
});

it('flutter widget should be child of element', async () => {
const container = document.createElement('div');
container.style.width = '100px';
container.style.height = '100px';
container.style.backgroundColor = 'red';
const element = document.createElement('flutter-text');
element.setAttribute('value', 'text');
container.appendChild(element);
document.body.appendChild(container);

await snapshot();
});

it('flutter widget should be child of element and the element should be child of flutter widget', async () => {
const container = document.createElement('flutter-container');
document.body.appendChild(container);

const childContainer = document.createElement('div');
container.appendChild(childContainer);

const fluttetText = document.createElement('flutter-text');
fluttetText.setAttribute('value', 'text');
childContainer.appendChild(fluttetText);

await snapshot();
});

it('should work with waterfall-flow', async () => {
const flutterContainer = document.createElement('waterfall-flow');
flutterContainer.style.height = '100vh';
flutterContainer.style.display = 'block';

document.body.appendChild(flutterContainer);

const colors = ['red', 'yellow', 'black', 'blue', 'green'];

for (let i = 0; i < 10; i++) {
const div = document.createElement('div');
div.style.width = '100%';
div.style.border = `1px solid ${colors[i % colors.length]}`;
div.appendChild(document.createTextNode(`${i}`));

const img = document.createElement('img');
img.src = 'https://gw.alicdn.com/tfs/TB1CxCYq5_1gK0jSZFqXXcpaXXa-128-90.png';
div.appendChild(img);
img.style.width = '100px';

flutterContainer.appendChild(div);
}

await snapshot();
});
});

describe('custom html element', () => {
Expand Down
13 changes: 10 additions & 3 deletions kraken/lib/src/dom/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:flutter/scheduler.dart';
import 'package:kraken/css.dart';
import 'package:kraken/dom.dart';
import 'package:kraken/rendering.dart';
import 'package:kraken/widget.dart';
import 'package:kraken/src/dom/element_event.dart';
import 'package:kraken/src/dom/element_view.dart';
import 'package:meta/meta.dart';
Expand Down Expand Up @@ -577,7 +578,10 @@ class Element extends Node
}

if (renderer != null) {
_attachRenderBoxModel(parent.renderer!, renderer!, after: after);
// If element attach WidgetElement, render obeject should be attach to render tree when mount.
if (parent is! WidgetElement) {
_attachRenderBoxModel(parent.renderer!, renderer!, after: after);
}

// Flush pending style before child attached.
style.flushPendingProperties();
Expand Down Expand Up @@ -636,7 +640,7 @@ class Element extends Node
RenderLayoutBox? renderLayoutBox = _renderLayoutBox;
if (isRendererAttached) {
// Only append child renderer when which is not attached.
if (!child.isRendererAttached && renderLayoutBox != null) {
if (!child.isRendererAttached && renderLayoutBox != null && this is! WidgetElement) {
RenderBox? after;
RenderLayoutBox? scrollingContentBox = renderLayoutBox.renderScrollingContent;
if (scrollingContentBox != null) {
Expand Down Expand Up @@ -805,7 +809,10 @@ class Element extends Node
_updateRenderBoxModel();
// Attach renderBoxModel to parent if change from `display: none` to other values.
if (!isRendererAttached && parentElement != null && parentElement!.isRendererAttached) {
_addToContainingBlock(after: previousSibling?.renderer);
// If element attach WidgetElement, render obeject should be attach to render tree when mount.
if (parentNode is! WidgetElement) {
_addToContainingBlock(after: previousSibling?.renderer);
}
ensureChildAttached();
}
}
Expand Down
3 changes: 3 additions & 0 deletions kraken/lib/src/dom/node.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:kraken/dom.dart';
import 'package:meta/meta.dart';
import 'package:kraken/widget.dart';

enum NodeType {
ELEMENT_NODE,
Expand Down Expand Up @@ -71,6 +72,8 @@ abstract class LifecycleCallbacks {
}

abstract class Node extends EventTarget implements RenderObjectNode, LifecycleCallbacks {
KrakenElementToFlutterElementAdaptor? flutterElement;
KrakenElementToWidgetAdaptor? flutterWidget;
List<Node> childNodes = [];
/// The Node.parentNode read-only property returns the parent of the specified node in the DOM tree.
Node? parentNode;
Expand Down
39 changes: 23 additions & 16 deletions kraken/lib/src/launcher/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/widgets.dart' show RenderObjectElement;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
Expand All @@ -24,6 +25,7 @@ import 'package:kraken/rendering.dart';
import 'package:kraken/widget.dart';
import 'package:kraken/src/dom/element_registry.dart' as element_registry;


import 'bundle.dart';

const int WINDOW_ID = -1;
Expand Down Expand Up @@ -769,6 +771,8 @@ class KrakenController {

UriParser? uriParser;

late RenderObjectElement rootFlutterElement;

static KrakenController? getControllerOfJSContextId(int? contextId) {
if (!_controllerMap.containsKey(contextId)) {
return null;
Expand Down Expand Up @@ -820,22 +824,25 @@ class KrakenController {

final GestureListener? _gestureListener;

KrakenController(String? name, double viewportWidth, double viewportHeight,
{bool showPerformanceOverlay = false,
enableDebug = false,
Color? background,
GestureListener? gestureListener,
KrakenNavigationDelegate? navigationDelegate,
KrakenMethodChannel? methodChannel,
this.widgetDelegate,
this.bundle,
this.onLoad,
this.onLoadError,
this.onJSError,
this.httpClientInterceptor,
this.devToolsService,
this.uriParser})
: _name = name,
KrakenController(
String? name,
double viewportWidth,
double viewportHeight, {
bool showPerformanceOverlay = false,
enableDebug = false,
Color? background,
GestureListener? gestureListener,
KrakenNavigationDelegate? navigationDelegate,
KrakenMethodChannel? methodChannel,
this.widgetDelegate,
this.bundle,
this.onLoad,
this.onLoadError,
this.onJSError,
this.httpClientInterceptor,
this.devToolsService,
this.uriParser,
}) : _name = name,
_gestureListener = gestureListener {
if (kProfileMode) {
PerformanceTiming.instance().mark(PERF_CONTROLLER_PROPERTY_INIT);
Expand Down
13 changes: 10 additions & 3 deletions kraken/lib/src/rendering/flow.dart
Original file line number Diff line number Diff line change
Expand Up @@ -542,8 +542,11 @@ class RenderFlowLayout extends RenderLayoutBox {
childConstraints = child.getConstraints();
} else if (child is RenderTextBox) {
childConstraints = child.getConstraints();
} else {
} else if (child is RenderPositionPlaceholder) {
childConstraints = BoxConstraints();
} else {
// Custom element.
childConstraints = constraints;
}

// Whether child need to layout
Expand Down Expand Up @@ -629,8 +632,12 @@ class RenderFlowLayout extends RenderLayoutBox {
runMainAxisExtent += childMainAxisExtent;

/// Calculate baseline extent of layout box
RenderStyle childRenderStyle = _getChildRenderStyle(child)!;
VerticalAlign verticalAlign = childRenderStyle.verticalAlign;
RenderStyle? childRenderStyle = _getChildRenderStyle(child);
VerticalAlign verticalAlign = VerticalAlign.baseline;
if (childRenderStyle != null) {
verticalAlign = childRenderStyle.verticalAlign;
}


bool isLineHeightValid = _isLineHeightValid(child);

Expand Down
Loading