diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d9465f..6587628 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## 2.5.4 + +- New `UIComponentDOMContext`. + +- `UIDOMGenerator`: + - Optimize `attachFutureElement` using `UIComponentDOMContext.uiComponent` to resolve `parentComponent`. + +- mercury_client: ^2.2.2 +- test: ^1.25.3 +- test_api: ^0.7.1 +- test_core: ^0.6.1 +- build_web_compilers: ^4.0.10 +- build_runner: ^2.4.9 + ## 2.5.3 - `testUI`: diff --git a/lib/src/bones_ui.dart b/lib/src/bones_ui.dart index 3effba8..242cd42 100644 --- a/lib/src/bones_ui.dart +++ b/lib/src/bones_ui.dart @@ -1,3 +1,3 @@ class BonesUI { - static const String version = '2.5.3'; + static const String version = '2.5.4'; } diff --git a/lib/src/bones_ui_component.dart b/lib/src/bones_ui_component.dart index 4cb88ea..8576197 100644 --- a/lib/src/bones_ui_component.dart +++ b/lib/src/bones_ui_component.dart @@ -1414,7 +1414,9 @@ abstract class UIComponent extends UIEventHandler { List toContentElements(dynamic rendered, {bool append = false, bool parseAttributes = true}) { try { - var list = _toContentElementsImpl(rendered, append); + var domContext = UIComponentDOMContext(this, domGenerator.domContext); + + var list = _toContentElementsImpl(rendered, append, domContext); if (parseAttributes) { _parseAttributes(content!.children); @@ -1450,7 +1452,8 @@ abstract class UIComponent extends UIEventHandler { static final _listDynamicRuntimeType = [].runtimeType; - List? toRenderableList(Object? list) { + List? toRenderableList(Object? list, + [DOMContext? domContext]) { if (list == null) return null; List renderableList; @@ -1483,8 +1486,9 @@ abstract class UIComponent extends UIEventHandler { return renderableList; } - List _toContentElementsImpl(Object? rendered, bool append) { - var renderableList = toRenderableList(rendered); + List _toContentElementsImpl( + Object? rendered, bool append, DOMContext? domContext) { + var renderableList = toRenderableList(rendered, domContext); var content = this.content!; @@ -1499,14 +1503,14 @@ abstract class UIComponent extends UIEventHandler { if (isListOfStrings(renderableList)) { var html = renderableList.join('\n'); - var values = _normalizeRenderListValue(content, html); + var values = _normalizeRenderListValue(content, html, domContext); var nodes = (values is List ? values : (values is Iterable ? values.toList() : [values])) .expand((e) => e is List ? e : [e]) .map((e) { - return _normalizeRenderListValue(content, e); + return _normalizeRenderListValue(content, e, domContext); }) .cast() .toList(); @@ -1534,22 +1538,27 @@ abstract class UIComponent extends UIEventHandler { var prevElemIndex = -1; for (var value in renderableList) { - prevElemIndex = _buildRenderList(value, renderedList2, prevElemIndex); + prevElemIndex = + _buildRenderList(value, renderedList2, prevElemIndex, domContext); } return renderedList2; } } - dynamic _normalizeRenderListValue(UIElement? content, value) { + dynamic _normalizeRenderListValue( + UIElement? content, value, DOMContext? domContext) { if (value is DOMNode) { - return value.buildDOM(generator: domGenerator, parent: content); + return value.buildDOM( + generator: domGenerator, parent: content, context: domContext); } else if (value is AsDOMElement) { var element = value.asDOMElement; - return element.buildDOM(generator: domGenerator, parent: content); + return element.buildDOM( + generator: domGenerator, parent: content, context: domContext); } else if (value is AsDOMNode) { var node = value.asDOMNode; - return node.buildDOM(generator: domGenerator, parent: content); + return node.buildDOM( + generator: domGenerator, parent: content, context: domContext); } else if (value is String) { var nodes = $html(value); return nodes; @@ -1579,12 +1588,12 @@ abstract class UIComponent extends UIEventHandler { } } - int _buildRenderList( - dynamic value, List renderedList, int prevElemIndex) { + int _buildRenderList(dynamic value, List renderedList, + int prevElemIndex, DOMContext? domContext) { if (value == null) return prevElemIndex; var content = this.content; - value = _normalizeRenderListValue(content, value); + value = _normalizeRenderListValue(content, value, domContext); if (value is UINode) { prevElemIndex = @@ -1596,17 +1605,19 @@ abstract class UIComponent extends UIEventHandler { prevElemIndex = _addElementToRenderList( value, value.content!, renderedList, prevElemIndex); } else if (value is UIAsyncContent) { - prevElemIndex = - _addUIAsyncContentToRenderList(value, renderedList, prevElemIndex); + prevElemIndex = _addUIAsyncContentToRenderList( + value, renderedList, prevElemIndex, domContext); } else if (value is List) { for (var elem in value) { - prevElemIndex = _buildRenderList(elem, renderedList, prevElemIndex); + prevElemIndex = + _buildRenderList(elem, renderedList, prevElemIndex, domContext); } } else if (value is Function) { try { // ignore: avoid_dynamic_calls var result = value(); - prevElemIndex = _buildRenderList(result, renderedList, prevElemIndex); + prevElemIndex = + _buildRenderList(result, renderedList, prevElemIndex, domContext); } catch (e, s) { UIConsole.error('Error calling function: $value', e, s); } @@ -1643,7 +1654,8 @@ abstract class UIComponent extends UIEventHandler { bool get isLoadingUIAsyncContent => _loadingAsyncContents.isNotEmpty; - void _resolveUIAsyncContentLoaded(UIAsyncContent asyncContent) { + void _resolveUIAsyncContentLoaded( + UIAsyncContent asyncContent, DOMContext? domContext) { if (!asyncContent.isLoaded) return; if (asyncContent.isLoaded && !asyncContent.hasAutoRefresh) { @@ -1693,7 +1705,8 @@ abstract class UIComponent extends UIEventHandler { var renderedList = []; if (maxContentIdx == null || maxContentIdx >= content!.nodes.length) { - _buildRenderList(loadedContent, renderedList, content!.nodes.length - 1); + _buildRenderList( + loadedContent, renderedList, content!.nodes.length - 1, domContext); _renderedElements!.addAll(renderedList); } else { @@ -1702,7 +1715,8 @@ abstract class UIComponent extends UIEventHandler { content!.nodes.remove(e); } - _buildRenderList(loadedContent, renderedList, content!.nodes.length - 1); + _buildRenderList( + loadedContent, renderedList, content!.nodes.length - 1, domContext); if (tail.isNotEmpty) { var renderedComponents = renderedList @@ -1734,14 +1748,14 @@ abstract class UIComponent extends UIEventHandler { _callPosAsyncRender(); } - int _addUIAsyncContentToRenderList( - UIAsyncContent asyncContent, List renderedList, int prevElemIndex) { + int _addUIAsyncContentToRenderList(UIAsyncContent asyncContent, + List renderedList, int prevElemIndex, DOMContext? domContext) { if (!asyncContent.isLoaded || asyncContent.isExpired || asyncContent.hasAutoRefresh) { _loadingAsyncContents.add(asyncContent); asyncContent.onLoadContent.listen((c) { - _resolveUIAsyncContentLoaded(asyncContent); + _resolveUIAsyncContentLoaded(asyncContent, domContext); }, singletonIdentifier: this); } @@ -1755,8 +1769,8 @@ abstract class UIComponent extends UIEventHandler { var renderIdx = renderedList.length; - prevElemIndex = - _buildRenderList(asyncContent.content, renderedList, prevElemIndex); + prevElemIndex = _buildRenderList( + asyncContent.content, renderedList, prevElemIndex, domContext); var rendered = renderedList.sublist(renderIdx).toList(); diff --git a/lib/src/bones_ui_generator.dart b/lib/src/bones_ui_generator.dart index d5054d4..2b65cbc 100644 --- a/lib/src/bones_ui_generator.dart +++ b/lib/src/bones_ui_generator.dart @@ -300,6 +300,18 @@ abstract class ElementGeneratorBase extends ElementGenerator { } } +class UIComponentDOMContext extends DOMContext { + final UIComponent uiComponent; + + UIComponentDOMContext(this.uiComponent, DOMContext? parent) + : super(parent: parent, intlMessageResolver: parent?.intlMessageResolver); + + @override + String toString() { + return 'UIComponentDOMContext{viewport: $viewport, resolveCSSViewportUnit: $resolveCSSViewportUnit resolveCSSURL: $resolveCSSURL}@$uiComponent'; + } +} + /// A [DOMGenerator] (from package `dom_builder`) /// able to generate [UIElement] (from `dart:html`). class UIDOMGenerator extends DOMGeneratorDartHTMLImpl { @@ -438,8 +450,14 @@ class UIDOMGenerator extends DOMGeneratorDartHTMLImpl { futureElementResolved, treeMap, context); if (futureElementResolved is UIElement) { - var parentComponent = - UIRoot.getInstance()!.findUIComponentByChild(futureElementResolved); + UIComponent? parentComponent; + + if (context is UIComponentDOMContext) { + parentComponent = context.uiComponent; + } else { + parentComponent = + UIRoot.getInstance()!.findUIComponentByChild(futureElementResolved); + } if (parentComponent != null) { parentComponent.componentInternals diff --git a/pubspec.yaml b/pubspec.yaml index 9c59dc5..3ef53dd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: bones_ui description: Bones_UI - An intuitive and user-friendly Web User Interface framework for Dart. -version: 2.5.3 +version: 2.5.4 homepage: https://github.com/Colossus-Services/bones_ui environment: @@ -18,7 +18,7 @@ dependencies: json_object_mapper: ^2.0.1 swiss_knife: ^3.2.0 statistics: ^1.1.0 - mercury_client: ^2.2.1 + mercury_client: ^2.2.2 dynamic_call: ^2.0.1 project_template: ^1.1.0 resource_portable: ^3.1.0 @@ -33,16 +33,16 @@ dependencies: args: ^2.4.2 logging: ^1.2.0 path: ^1.9.0 - test: ^1.25.2 - test_api: ^0.7.0 - test_core: ^0.6.0 + test: ^1.25.3 + test_api: ^0.7.1 + test_core: ^0.6.1 stream_channel: ^2.1.2 stack_trace: ^1.11.1 dev_dependencies: - build_web_compilers: ^4.0.9 - build_runner: ^2.4.8 + build_web_compilers: ^4.0.10 + build_runner: ^2.4.9 lints: ^3.0.0 dependency_validator: ^3.2.3