Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
add Material fix Opacity
  • Loading branch information
peixinli committed Feb 24, 2024
commit d0361d5ae4b397353eb72798c98873927d2478c3
3,338 changes: 3,338 additions & 0 deletions packages/rfw/coverage/lcov.info

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/rfw/lib/src/flutter/argument_decoders.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import 'runtime.dart';
/// This inherited widget allows a duration and a curve (defaulting to 200ms and
/// [Curves.fastOutSlowIn]) to be set as the default to use when local widgets
/// use the [ArgumentsDecoder.curve] and [ArgumentsDecoder.duration] methods and
/// find that the [DataSource] has no explicit curve or duration.
/// find that the [DataSource] has no explicit curve or duration.f
class AnimationDefaults extends InheritedWidget {
/// Configures an [AnimanionDefaults] widget.
///
Expand Down Expand Up @@ -485,7 +485,7 @@ class ArgumentDecoders {
return BoxDecoration(
color: color(source, [...key, 'color']),
image: decorationImage(source, [...key, 'image']),
border: border(source, [...key, 'border']),
border: border(source, [...key, 'bordefr']),
borderRadius: borderRadius(source, [...key, 'borderRadius']),
boxShadow: list<BoxShadow>(source, [...key, 'boxShadow'], boxShadow),
gradient: gradient(source, [...key, 'gradient']),
Expand Down
1 change: 1 addition & 0 deletions packages/rfw/lib/src/flutter/core_widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ Map<String, LocalWidgetBuilder> get _coreWidgetsDefinitions => <String, LocalWid
opacity: source.v<double>(['opacity']) ?? 0.0,
onEnd: source.voidHandler(['onEnd']),
alwaysIncludeSemantics: source.v<bool>(['alwaysIncludeSemantics']) ?? true,
child: source.optionalChild(['child']),
);
},

Expand Down
94 changes: 56 additions & 38 deletions packages/rfw/lib/src/flutter/material_widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import 'runtime.dart';
/// * [InkWell]
/// * [LinearProgressIndicator]
/// * [ListTile]
/// * [Material]
/// * [OutlinedButton]
/// * [Scaffold]
/// * [TextButton]
Expand Down Expand Up @@ -339,44 +340,44 @@ Map<String, LocalWidgetBuilder> get _materialWidgetsDefinitions => <String, Loca
);
},

'InkResponse': (BuildContext context, DataSource source) {
return InkResponse(
onTap: source.voidHandler(['onTap']),
onTapDown: source.handler(['onTapDown'], (VoidCallback trigger) => (TapDownDetails details) => trigger()),
onTapUp: source.handler(['onTapUp'], (VoidCallback trigger) => (TapUpDetails details) => trigger()),
onTapCancel: source.voidHandler(['onTapCancel']),
onDoubleTap: source.voidHandler(['onDoubleTap']),
onLongPress: source.voidHandler(['onLongPress']),
onSecondaryTap: source.voidHandler(['onSecondaryTap']),
onSecondaryTapUp: source.handler(['onSecondaryTapUp'], (VoidCallback trigger) => (TapUpDetails details) => trigger()),
onSecondaryTapDown: source.handler(['onSecondaryTapDown'], (VoidCallback trigger) => (TapDownDetails details) => trigger()),
onSecondaryTapCancel: source.voidHandler(['onSecondaryTapCancel']),
onHighlightChanged: source.handler(['onHighlightChanged'], (VoidCallback trigger) => (bool highlighted) => trigger()),
onHover: source.handler(['onHover'], (VoidCallback trigger) => (bool hovered) => trigger()),
// MouseCursor? mouseCursor,
containedInkWell: source.v<bool>(['containedInkWell']) ?? false,
highlightShape: ArgumentDecoders.enumValue<BoxShape>(BoxShape.values, source, ['highlightShape']) ?? BoxShape.circle,
radius: source.v<double>(['radius']),
borderRadius: ArgumentDecoders.borderRadius(source, ['borderRadius'])
?.resolve(Directionality.of(context)),
customBorder: ArgumentDecoders.shapeBorder(source, ['customBorder']),
focusColor: ArgumentDecoders.color(source, ['focusColor']),
hoverColor: ArgumentDecoders.color(source, ['hoverColor']),
highlightColor: ArgumentDecoders.color(source, ['highlightColor']),
// MaterialStateProperty<Color?>? overlayColor,
splashColor: ArgumentDecoders.color(source, ['splashColor']),
// InteractiveInkFeatureFactory? splashFactory,
enableFeedback: source.v<bool>(['enableFeedback']) ?? true,
excludeFromSemantics: source.v<bool>(['excludeFromSemantics']) ?? false,
// FocusNode? focusNode,
canRequestFocus: source.v<bool>(['canRequestFocus']) ?? true,
onFocusChange: source.handler(['onFocusChange'], (VoidCallback trigger) => (bool focus) => trigger()),
autofocus: source.v<bool>(['autofocus']) ?? false,
hoverDuration:
ArgumentDecoders.duration(source, ['hoverDuration'], context),
child: source.child(['child']),
);
},
// 'InkResponse': (BuildContext context, DataSource source) {
// return InkResponse(
// onTap: source.voidHandler(['onTap']),
// onTapDown: source.handler(['onTapDown'], (VoidCallback trigger) => (TapDownDetails details) => trigger()),
// onTapUp: source.handler(['onTapUp'], (VoidCallback trigger) => (TapUpDetails details) => trigger()),
// onTapCancel: source.voidHandler(['onTapCancel']),
// onDoubleTap: source.voidHandler(['onDoubleTap']),
// onLongPress: source.voidHandler(['onLongPress']),
// onSecondaryTap: source.voidHandler(['onSecondaryTap']),
// onSecondaryTapUp: source.handler(['onSecondaryTapUp'], (VoidCallback trigger) => (TapUpDetails details) => trigger()),
// onSecondaryTapDown: source.handler(['onSecondaryTapDown'], (VoidCallback trigger) => (TapDownDetails details) => trigger()),
// onSecondaryTapCancel: source.voidHandler(['onSecondaryTapCancel']),
// onHighlightChanged: source.handler(['onHighlightChanged'], (VoidCallback trigger) => (bool highlighted) => trigger()),
// onHover: source.handler(['onHover'], (VoidCallback trigger) => (bool hovered) => trigger()),
// // MouseCursor? mouseCursor,
// containedInkWell: source.v<bool>(['containedInkWell']) ?? false,
// highlightShape: ArgumentDecoders.enumValue<BoxShape>(BoxShape.values, source, ['highlightShape']) ?? BoxShape.circle,
// radius: source.v<double>(['radius']),
// borderRadius: ArgumentDecoders.borderRadius(source, ['borderRadius'])
// ?.resolve(Directionality.of(context)),
// customBorder: ArgumentDecoders.shapeBorder(source, ['customBorder']),
// focusColor: ArgumentDecoders.color(source, ['focusColor']),
// hoverColor: ArgumentDecoders.color(source, ['hoverColor']),
// highlightColor: ArgumentDecoders.color(source, ['highlightColor']),
// // MaterialStateProperty<Color?>? overlayColor,
// splashColor: ArgumentDecoders.color(source, ['splashColor']),
// // InteractiveInkFeatureFactory? splashFactory,
// enableFeedback: source.v<bool>(['enableFeedback']) ?? true,
// excludeFromSemantics: source.v<bool>(['excludeFromSemantics']) ?? false,
// // FocusNode? focusNode,
// canRequestFocus: source.v<bool>(['canRequestFocus']) ?? true,
// onFocusChange: source.handler(['onFocusChange'], (VoidCallback trigger) => (bool focus) => trigger()),
// autofocus: source.v<bool>(['autofocus']) ?? false,
// hoverDuration:
// ArgumentDecoders.duration(source, ['hoverDuration'], context),
// child: source.child(['child']),
// );
// },

'InkWell': (BuildContext context, DataSource source) {
// not implemented: onHighlightChanged, onHover; mouseCursor; focusColor, hoverColor, highlightColor, overlayColor, splashColor; splashFactory; focusNode, onFocusChange
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since you've implemented some of these for InkResponse, we might as well add them here too for consistency

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Expand Down Expand Up @@ -436,6 +437,23 @@ Map<String, LocalWidgetBuilder> get _materialWidgetsDefinitions => <String, Loca
);
},

'Material': (BuildContext context, DataSource source) {
return Material(
type: ArgumentDecoders.enumValue<MaterialType>(MaterialType.values,source, ['type']) ?? MaterialType.canvas,
elevation: source.v<double>(['elevation']) ?? 0.0,
color: ArgumentDecoders.color(source, ['color']),
shadowColor: ArgumentDecoders.color(source, ['shadowColor']),
surfaceTintColor: ArgumentDecoders.color(source, ['surfaceTintColor']),
textStyle: ArgumentDecoders.textStyle(source, ['textStyle']),
borderRadius: ArgumentDecoders.borderRadius(source, ['borderRadius']),
shape: ArgumentDecoders.shapeBorder(source, ['shape']),
borderOnForeground: source.v<bool>(['borderOnForeground']) ?? true,
clipBehavior: ArgumentDecoders.enumValue<Clip>(Clip.values, source, ['clipBehavior']) ?? Clip.none,
animationDuration: ArgumentDecoders.duration(source, ['animationDuration'], context),
child: source.child(['child']),
);
},

'OutlinedButton': (BuildContext context, DataSource source) {
// not implemented: buttonStyle, focusNode
return OutlinedButton(
Expand Down
5 changes: 4 additions & 1 deletion packages/rfw/test/core_widgets_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ void main() {

runtime.update(const LibraryName(<String>['test']), parseLibraryFile('''
import core;
widget root = Opacity(onEnd: event 'end' {});
widget root = Opacity(
onEnd: event 'end' {},
child: Placeholder(),
);
'''));
await tester.pump();
expect(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).onEnd, isNot(isNull));
Expand Down
Binary file modified packages/rfw/test/goldens/argument_decoders_test.containers.png
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.
142 changes: 105 additions & 37 deletions packages/rfw/test/material_widgets_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,84 @@ void main() {
);
});

testWidgets('Implement InkResponse properties', (WidgetTester tester) async {
// testWidgets('Implement InkResponse properties', (WidgetTester tester) async {
// final Runtime runtime = setupRuntime();
// final DynamicContent data = DynamicContent();
// final List<String> eventLog = <String>[];
// await tester.pumpWidget(
// MaterialApp(
// theme: ThemeData(useMaterial3: false),
// home: RemoteWidget(
// runtime: runtime,
// data: data,
// widget: const FullyQualifiedWidgetName(testName, 'root'),
// onEvent: (String eventName, DynamicMap eventArguments) {
// eventLog.add('$eventName $eventArguments');
// },
// ),
// ),
// );
// expect(
// tester.takeException().toString(),
// contains('Could not find remote widget named'),
// );

// runtime.update(testName, parseLibraryFile('''
// import core;
// import material;
// widget root = Scaffold(
// body: Center(
// child: InkResponse(
// onTap: event 'onTap' {},
// onHover: event 'onHover' {},
// radius: 1.0,
// borderRadius: [{x: 8.0, y: 8.0}, {x: 8.0, y: 8.0}, {x: 8.0, y: 8.0}, {x: 8.0, y: 8.0}],
// hoverColor: 0xFF00FF00,
// splashColor: 0xAA0000FF,
// highlightColor: 0xAAFF0000,
// containedInkWell: true,
// highlightShape: 'circle',
// child: Text(text: 'InkResponse'),
// ),
// ),
// );
// '''));
// await tester.pump();

// expect(find.byType(InkResponse), findsOneWidget);

// // Hover
// final Offset center = tester.getCenter(find.byType(InkResponse));
// final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
// await gesture.addPointer();
// addTearDown(gesture.removePointer);
// await gesture.moveTo(center);
// await tester.pumpAndSettle();

// await expectLater(
// find.byType(RemoteWidget),
// matchesGoldenFile('goldens/material_test.ink_response_hover.png'),
// skip: !runGoldens,
// );
// expect(eventLog, contains('onHover {}'));

// // Tap
// await gesture.down(center);
// await tester.pump(); // start gesture
// await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way

// await expectLater(
// find.byType(RemoteWidget),
// matchesGoldenFile('goldens/material_test.ink_response_tap.png'),
// skip: !runGoldens,
// );
// await gesture.up();
// await tester.pump();

// expect(eventLog, contains('onTap {}'));
// });

testWidgets('Implement Material properties', (WidgetTester tester) async {
final Runtime runtime = setupRuntime();
final DynamicContent data = DynamicContent();
final List<String> eventLog = <String>[];
Expand All @@ -465,53 +542,44 @@ void main() {
runtime.update(testName, parseLibraryFile('''
import core;
import material;
widget root = Scaffold(
body: Center(
child: InkResponse(
onTap: event 'onTap' {},
onHover: event 'onHover' {},
radius: 1.0,
borderRadius: [{x: 8.0, y: 8.0}, {x: 8.0, y: 8.0}, {x: 8.0, y: 8.0}, {x: 8.0, y: 8.0}],
hoverColor: 0xFF00FF00,
splashColor: 0xAA0000FF,
highlightColor: 0xAAFF0000,
containedInkWell: true,
highlightShape: 'circle',
child: Text(text: 'InkResponse'),
),
widget root = Material(
type: 'circle',
elevation: 6.0,
color: 0xFF0000FF,
shadowColor: 0xFF00FF00,
surfaceTintColor: 0xff0000ff,
animationDuration: 300,
borderOnForeground: false,
child: SizedBox(
width: 20.0,
height: 20.0,
),
);
'''));
await tester.pump();

// Hover
final Offset center = tester.getCenter(find.byType(InkResponse));
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
addTearDown(gesture.removePointer);
await gesture.moveTo(center);
await tester.pumpAndSettle();

expect(tester.widget<Material>(find.byType(Material)).animationDuration, const Duration(milliseconds: 300));
expect(tester.widget<Material>(find.byType(Material)).borderOnForeground, false);
await expectLater(
find.byType(RemoteWidget),
matchesGoldenFile('goldens/material_test.ink_response_hover.png'),
matchesGoldenFile('goldens/material_test.material_properties.png'),
skip: !runGoldens,
);
expect(eventLog, contains('onHover {}'));

// Tap
await gesture.down(center);
await tester.pump(); // start gesture
await tester.pump(const Duration(milliseconds: 200)); // wait for splash to be well under way

await expectLater(
find.byType(RemoteWidget),
matchesGoldenFile('goldens/material_test.ink_response_tap.png'),
skip: !runGoldens,
);
await gesture.up();
runtime.update(testName, parseLibraryFile('''
import core;
import material;
widget root = Material(
clipBehavior: 'antiAlias',
shape: { type: 'circle', side: { width: 10.0, color: 0xFF0066FF } },
child: SizedBox(
width: 20.0,
height: 20.0,
),
);
'''));
await tester.pump();

expect(eventLog, contains('onTap {}'));
expect(tester.widget<Material>(find.byType(Material)).clipBehavior, Clip.antiAlias);
});
}