Skip to content

Commit

Permalink
Merge v2.5.12 - Optimize
Browse files Browse the repository at this point in the history
 - `UIComponent`:
   - Optimize `parseClasses`, `configureClasses`, `appendClasses` and `appendStyle`.
   - `_callRenderImpl`: optimize check if parent contains content.
   - `_normalizeRenderListValue`: optimize type check order.
   - Improve null-safe code.

 - `bones_ui_layout`: optimize.

 - dom_tools: ^2.3.2
 - dom_builder: ^2.2.7
 - swiss_knife: ^3.2.3
 - yaml: ^3.1.3
 - test: ^1.25.14
 - stream_channel: ^2.1.3
 - stack_trace: ^1.12.1
  • Loading branch information
gmpassos authored Dec 21, 2024
2 parents 430da77 + fb276d9 commit c4acd53
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 106 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
## 2.5.12

- `UIComponent`:
- Optimize `parseClasses`, `configureClasses`, `appendClasses` and `appendStyle`.
- `_callRenderImpl`: optimize check if parent contains content.
- `_normalizeRenderListValue`: optimize type check order.
- Improve null-safe code.

- `bones_ui_layout`: optimize.

- dom_tools: ^2.3.2
- dom_builder: ^2.2.7
- swiss_knife: ^3.2.3
- yaml: ^3.1.3
- test: ^1.25.14
- stream_channel: ^2.1.3
- stack_trace: ^1.12.1

## 2.5.11

- `UIComponent`:
Expand Down
2 changes: 1 addition & 1 deletion lib/src/bones_ui.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
class BonesUI {
static const String version = '2.5.11';
static const String version = '2.5.12';
}
236 changes: 155 additions & 81 deletions lib/src/bones_ui_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -467,80 +467,132 @@ abstract class UIComponent extends UIEventHandler {

static final RegExp _classesEntryDelimiter = RegExp(r'[\s,;]+');

static List<String> parseClasses(dynamic classes1, [dynamic classes2]) {
var c1 = _parseClasses(classes1);
if (classes2 == null) return c1;

var c2 = _parseClasses(classes2);

var set = c1.toSet();
set.addAll(c2);

return set.toList();
static List<String> parseClasses(Object? classes1, [Object? classes2]) {
if (classes1 != null && classes2 != null) {
var c1 = _parseClasses(classes1);
var c2 = _parseClasses(classes2);

if (c1.isNotEmpty && c2.isNotEmpty) {
return {...c1, ...c2}.toList();
} else if (c1.isNotEmpty) {
return c1.length > 1 ? c1.toSet().toList() : c1;
} else if (c2.isNotEmpty) {
return c2.length > 1 ? c2.toSet().toList() : c2;
} else {
return <String>[];
}
} else if (classes1 != null) {
var c1 = _parseClasses(classes1);
return c1.length > 1 ? c1.toSet().toList() : c1;
} else if (classes2 != null) {
var c2 = _parseClasses(classes2);
return c2.length > 1 ? c2.toSet().toList() : c2;
} else {
return <String>[];
}
}

static List<String> _parseClasses(classes) => toFlatListOfStrings(classes,
delimiter: _classesEntryDelimiter, trim: true, ignoreEmpty: true);

void configureClasses(dynamic classes1,
[dynamic classes2, dynamic componentClasses]) {
void configureClasses(Object? classes1,
[Object? classes2, Object? componentClasses]) {
var content = this.content!;
content.classes.add('ui-component');

var classesNamesComponent = parseClasses(componentClasses);
content.classes.addAll(classesNamesComponent);
if (componentClasses != null) {
var classesNamesComponent = parseClasses(componentClasses);
content.classes.addAll(classesNamesComponent);
}

appendClasses(classes1, classes2);
}

void appendClasses(dynamic classes1, [dynamic classes2]) {
var classesNames = <String>[
...parseClasses(classes1),
...parseClasses(classes2)
];
void appendClasses(Object? classes1, [Object? classes2]) {
List<String> classesNames;
if (classes1 != null && classes2 != null) {
classesNames = <String>[
...parseClasses(classes1),
...parseClasses(classes2)
];
} else if (classes1 != null) {
classesNames = parseClasses(classes1);
} else if (classes2 != null) {
classesNames = parseClasses(classes2);
} else {
return;
}

var classesNamesRemove = classesNames
.where((e) => e.startsWith('!'))
.map((e) => e.substring(1))
.toList();

classesNames.removeWhere((s) => s.startsWith('!'));
if (classesNamesRemove.isNotEmpty) {
classesNames.removeWhere((s) => s.startsWith('!'));
}

var content = this.content!;

content.classes.addAll(classesNames);
content.classes.removeAll(classesNamesRemove);

if (classesNamesRemove.isNotEmpty) {
content.classes.removeAll(classesNamesRemove);
}
}

static final RegExp _cssEntryDelimiter = RegExp(r'\s*;\s*');

static List<String> parseStyle(style1) => toFlatListOfStrings(style1,
delimiter: _cssEntryDelimiter, trim: true, ignoreEmpty: true);

void configureStyle(dynamic style1,
[dynamic style2, dynamic componentStyle]) {
void configureStyle(Object? style1,
[Object? style2, Object? componentStyle]) {
appendStyle(componentStyle, style1, style2);
}

void appendStyle(dynamic style1, [dynamic style2, dynamic style3]) {
var styles1 = parseStyle(style1);
var styles2 = parseStyle(style2);
var styles3 = parseStyle(style3);
void appendStyle(Object? style1, [Object? style2, Object? style3]) {
List<String> allStyles;

styles1.addAll(styles2);
styles1.addAll(styles3);
if (style1 != null) {
var styles1 = parseStyle(style1);
if (style2 != null) {
var styles2 = parseStyle(style2);
if (style3 != null) {
var styles3 = parseStyle(style3);
allStyles = [...styles1, ...styles2, ...styles3];
} else {
allStyles = [...styles1, ...styles2];
}
} else {
allStyles = styles1;
}
} else if (style2 != null) {
var styles2 = parseStyle(style2);
if (style3 != null) {
var styles3 = parseStyle(style3);
allStyles = [...styles2, ...styles3];
} else {
allStyles = styles2;
}
} else if (style3 != null) {
allStyles = parseStyle(style3);
} else {
return;
}

if (styles1.isNotEmpty) {
var allStyles = styles1.join('; ');
if (allStyles.isNotEmpty) {
var allStylesLine = allStyles.join('; ');

var cssText = content!.style.cssText ?? '';
final content = this.content!;

var cssText = content.style.cssText ?? '';
if (cssText == '') {
cssText = allStyles;
cssText = allStylesLine;
} else {
cssText += allStyles;
cssText += allStylesLine;
}

content!.style.cssText = cssText;
content.style.cssText = cssText;
}
}

Expand Down Expand Up @@ -1234,29 +1286,41 @@ abstract class UIComponent extends UIEventHandler {
_renderCount++;
_requestRefresh = null;

var content = this.content;
var content = this.content!;

final parent = _parent;
if (parent != null) {
if (clearParent == UIComponentClearParent.onRender ||
(clearParent == UIComponentClearParent.onInitialRender &&
_renderCount == 1)) {
var nodes = List<UINode>.from(parent.nodes);
// content not added to parent:
if (!identical(content.parentNode, parent)) {
parent.nodes.clear();
parent.append(content);
}
// content already added, remove other nodes:
else {
var nodes = List<UINode>.from(parent.nodes);

var containsContent = false;
for (var node in nodes) {
if (identical(node, content)) {
containsContent = true;
} else {
node.remove();
}
}

var containsContent = false;
for (var node in nodes) {
if (identical(node, content)) {
containsContent = true;
} else {
node.remove();
// Improbable to happen, unless it's an odd browser:
if (!containsContent) {
parent.append(content);
}
}

if (!containsContent) {
parent.append(content!);
} else {
var appended = identical(content.parentNode, parent);
if (!appended) {
parent.append(content);
}
} else if (!parent.nodes.contains(content)) {
parent.append(content!);
}
}

Expand Down Expand Up @@ -1731,25 +1795,15 @@ abstract class UIComponent extends UIEventHandler {
if (value is DOMNode) {
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, context: domContext);
} else if (value is AsDOMNode) {
var node = value.asDOMNode;
return node.buildDOM(
generator: domGenerator, parent: content, context: domContext);
} else if (value is String) {
var nodes = $html(value);
return nodes;
} else if (value is Map ||
(value is List && listMatchesAll(value, (dynamic e) => e is Map))) {
var jsonRender = JSONRender.fromJSON(value)
..renderMode = JSONRenderMode.view
..addAllKnownTypeRenders();
return jsonRender.render();
} else if (value is Iterable && value is! List) {
return value.toList();
} else if (value is List) {
return value;
} else if (value is UINode) {
return value;
} else if (value is Function) {
return value;
} else if (value is Future) {
var asyncContent = UIAsyncContent.future(
value,
Expand All @@ -1763,6 +1817,24 @@ abstract class UIComponent extends UIEventHandler {
properties: {'__Future__': value},
)..parentUIComponent = this;
return asyncContent;
} else if (value is UIComponent) {
return value;
} else if (value is Iterable) {
return value.toList();
} else if (value is AsDOMElement) {
var element = value.asDOMElement;
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, context: domContext);
} else if (value is Map ||
(value is List && listMatchesAll(value, (dynamic e) => e is Map))) {
var jsonRender = JSONRender.fromJSON(value)
..renderMode = JSONRenderMode.view
..addAllKnownTypeRenders();
return jsonRender.render();
} else {
return value;
}
Expand Down Expand Up @@ -1845,17 +1917,18 @@ abstract class UIComponent extends UIEventHandler {
var prevRendered = _renderedAsyncContents[asyncContent];
if (prevRendered == null) return;

if (_renderedElements == null) {
final renderedElements = _renderedElements;
if (renderedElements == null) {
return;
}

int? minRenderedElementsIdx;

for (var e in prevRendered) {
if (e == null) continue;
var idx = _renderedElements!.indexOf(e);
var idx = renderedElements.indexOf(e);
if (idx >= 0) {
_renderedElements!.removeAt(idx);
renderedElements.removeAt(idx);
if (minRenderedElementsIdx == null || idx < minRenderedElementsIdx) {
minRenderedElementsIdx = idx;
}
Expand All @@ -1869,11 +1942,12 @@ abstract class UIComponent extends UIEventHandler {

int? maxContentIdx;

for (var node in content!.nodes.toList()) {
final content = this.content!;
for (var node in content.nodes.toList()) {
if (prevElements.contains(node)) {
var idx = content!.nodes.indexOf(node);
var idx = content.nodes.indexOf(node);
if (idx >= 0) {
content!.nodes.removeAt(idx);
content.nodes.removeAt(idx);
if (maxContentIdx == null || idx > maxContentIdx) {
maxContentIdx = idx;
}
Expand All @@ -1884,19 +1958,19 @@ abstract class UIComponent extends UIEventHandler {
var loadedContent = asyncContent.content;

var renderedList = [];
if (maxContentIdx == null || maxContentIdx >= content!.nodes.length) {
if (maxContentIdx == null || maxContentIdx >= content.nodes.length) {
_buildRenderList(
loadedContent, renderedList, content!.nodes.length - 1, domContext);
loadedContent, renderedList, content.nodes.length - 1, domContext);

_renderedElements!.addAll(renderedList);
renderedElements.addAll(renderedList);
} else {
var tail = content!.nodes.sublist(maxContentIdx).toList();
var tail = content.nodes.sublist(maxContentIdx).toList();
for (var e in tail) {
content!.nodes.remove(e);
content.nodes.remove(e);
}

_buildRenderList(
loadedContent, renderedList, content!.nodes.length - 1, domContext);
loadedContent, renderedList, content.nodes.length - 1, domContext);

if (tail.isNotEmpty) {
var renderedComponents = renderedList
Expand All @@ -1907,18 +1981,18 @@ abstract class UIComponent extends UIEventHandler {
tail.removeWhere(
(e) => renderedList.contains(e) || renderedComponents.contains(e));

content!.nodes.addAll(tail);
content.nodes.addAll(tail);
}

minRenderedElementsIdx ??= 0;
_renderedElements!.insertAll(minRenderedElementsIdx, renderedList);
renderedElements.insertAll(minRenderedElementsIdx, renderedList);
}

_ensureAllRendered(renderedList);

try {
_parseAttributes(content!.children);
_parseAttributesPosRender(content!.children);
_parseAttributes(content.children);
_parseAttributesPosRender(content.children);
} catch (e, s) {
UIConsole.error('$this _parseAttributesPosRender(...) error', e, s);
}
Expand Down
Loading

0 comments on commit c4acd53

Please sign in to comment.