Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 7.1.1

- A badge with no child no longer fills loose constraints, so a badge set
to wrap its content sizes to the badge.
- Chips no longer throw when no `Material` ancestor is present.

## 7.1.0

- Require codelessly_api 5.1.0.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,15 @@ class PassiveBadgeWidget extends StatelessWidget {
return AdaptiveNodeBox(
node: node,
// Without a child, the badge keeps its own size and sits at its
// alignment inside the node's box.
// alignment inside the node's box. The size factors keep it from
// filling loose constraints when the node wraps its content.
child: childNode == null
? Align(alignment: alignment, child: badge)
? Align(
alignment: alignment,
widthFactor: 1,
heightFactor: 1,
child: badge,
)
: badge,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,11 @@ class TransformerChip extends StatelessWidget {
),
};

return AdaptiveNodeBox(node: node, child: chip);
// Chips draw ink and need a Material ancestor, which a layout may not
// provide (e.g. when measured offscreen).
return AdaptiveNodeBox(
node: node,
child: Material(type: MaterialType.transparency, child: chip),
);
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: codelessly_sdk
description: Codelessly CloudUI™ - Server-driven UI for Flutter. Supercharge your Flutter apps with dynamic UI and real-time updates. Build and publish UI without code!
version: 7.1.0
version: 7.1.1
homepage: https://codelessly.com/
repository: https://github.com/Codelessly/CodelesslySDK
issue_tracker: https://github.com/Codelessly/CodelesslySDK/issues
Expand Down
75 changes: 75 additions & 0 deletions test/smoke_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -362,4 +362,79 @@ void main() {
expect(PassiveSegmentedButtonWidget.parseSelection('[]'), isEmpty);
expect(PassiveSegmentedButtonWidget.parseSelection('a'), {'a'});
});

// The editor measures wrap-content nodes offscreen, under loose constraints
// and without a Material ancestor.
testWidgets('badge, chip and segmented button wrap their content', (
tester,
) async {
const measure = WidgetBuildSettings(
debugLabel: 'test',
withMargins: false,
withConstraints: false,
withAlignment: false,
isPreview: true,
);
final nodes = <BaseNode>[
BadgeNode(
id: 'badge',
name: 'Badge',
basicBoxLocal: NodeBox(0, 0, 48, 48),
horizontalFit: SizeFit.shrinkWrap,
verticalFit: SizeFit.shrinkWrap,
properties: BadgeProperties(label: '3'),
),
for (final type in ChipType.values)
ChipNode(
id: 'chip-${type.name}',
name: 'Chip',
basicBoxLocal: NodeBox(0, 0, 100, 32),
horizontalFit: SizeFit.shrinkWrap,
verticalFit: SizeFit.shrinkWrap,
properties: ChipProperties(chipType: type, label: 'Label'),
),
SegmentedButtonNode(
id: 'segmented',
name: 'Segmented',
basicBoxLocal: NodeBox(0, 0, 200, 40),
horizontalFit: SizeFit.shrinkWrap,
verticalFit: SizeFit.shrinkWrap,
properties: SegmentedButtonProperties(
segments: const [
ButtonSegmentModel(value: 'a', label: 'A'),
ButtonSegmentModel(value: 'b', label: 'B'),
],
selected: const ['a'],
),
),
];
final manager = managerFor(nodes);
for (final node in nodes) {
final key = GlobalKey();
await tester.pumpWidget(
ChangeNotifierProvider<CodelesslyContext>.value(
value: CodelesslyContext.empty(),
// MaterialApp without a Scaffold: localizations but no Material.
child: MaterialApp(
home: Center(
child: Builder(
builder: (context) => KeyedSubtree(
key: key,
child: manager.buildWidgetByID(
node.id,
context,
settings: measure,
),
),
),
),
),
),
);
expect(tester.takeException(), isNull, reason: node.id);
final size = tester.getSize(find.byKey(key));
expect(size.width, lessThan(300), reason: '${node.id} $size');
expect(size.height, lessThan(100), reason: '${node.id} $size');
}
});
}
Loading