relation 3.1.0 relation: ^3.1.0 copied to clipboard
the stream representation of the relations of the entities and widget utilities
Relation #
This package is part of the SurfGear toolkit made by Surf.
About #
The stream representation of the relations of the entities and widget utilities
Usage #
Main classes:
- StreamedAction 1.1 ScrollOffsetAction 1.2 TextEditingAction
- Builder 2.1 EntityStateBuilder 2.2 StreamedStateBuilder 2.3 TextfieldStateBuilder
- StreamedState
- EntityStreamedState
Actions #
StreamedAction #
It's wrapper over an action on screen. It may be a tap on button, text changes, focus changes and so on.
SomeWidget(
onTap: someAction.accept,
)
...
someAction.action.listen(doSomething);
ScrollOffsetAction #
The action that fires when the value changes when scrolling.
testWidgets(
'ScrollOffsetAction test',
(WidgetTester tester) async {
final action = ScrollOffsetStreamedAction((onChanged) {
expect(1.0, onChanged);
});
await tester.pumpWidget(MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(
title: Text('test'),
),
body: ListView(
controller: action.controller,
scrollDirection: Axis.vertical,
children: <Widget>[
Text('test'),
Text('test'),
Text('test'),
],
),
),
));
action.controller.jumpTo(1.0);
},
);
TextEditingStreamedAction #
Currently experimental.
An action that fires when a text field receives new characters
test('TextEditingAction test', () {
final action = TextEditingAction((onChanged) {
expect('test', onChanged);
});
action.controller.text = 'test';
});
Builder #
Builders are widgets that listen to a change in a stream and provide new data to child widgets
StreamedStateBuilder #
Updates child widget when an answer arrives
testWidgets(
'StreamedStateBuilder test',
(WidgetTester tester) async {
final testData = StreamedState<String>('test');
final streamedStateBuilder = StreamedStateBuilder<String>(
streamedState: testData,
builder: (context, data) {
return Text(data);
});
await tester.pumpWidget(
MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: streamedStateBuilder,
),
),
);
final textFinder = find.text('test');
expect(textFinder, findsOneWidget);
},
);
EntityStateBuilder #
This builder has three states onResponse, onError, onLoading
testWidgets(
'StreamedStateBuilder accept test',
(WidgetTester tester) async {
final testData = EntityStreamedState<String>(EntityState(data: 'test'));
final streamedStateBuilder = EntityStateBuilder<String>(
streamedState: testData,
child: (context, data) {
return Text(data);
},
);
await tester.pumpWidget(
MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: streamedStateBuilder,
),
),
);
expect(streamedStateBuilder.streamedState.value.data, 'test');
final testFinder = find.text('test');
expect(testFinder, findsOneWidget);
await testData.error();
},
);
testWidgets(
'StreamedStateBuilder error test',
(WidgetTester tester) async {
final testData = EntityStreamedState<String>();
final streamedStateBuilder = EntityStateBuilder<String>(
streamedState: testData,
child: (context, data) {
return Text('test');
},
errorChild: Text('error_text'),
);
unawaited(testData.error(Exception()));
await tester.pumpWidget(
MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: streamedStateBuilder,
),
),
);
final errorFinder = find.text('error_text');
expect(errorFinder, findsOneWidget);
},
);
testWidgets(
'StreamedStateBuilder loading test',
(WidgetTester tester) async {
final testData = EntityStreamedState<String>();
final streamedStateBuilder = EntityStateBuilder<String>(
streamedState: testData,
child: (context, data) {
return Text('test');
},
loadingChild: Text('loading_child'),
);
unawaited(testData.loading());
await tester.pumpWidget(
MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: streamedStateBuilder,
),
),
);
final loadingFinder = find.text('loading_child');
expect(loadingFinder, findsOneWidget);
},
);
TextFieldStateBuilder #
Wrapper over TextFieldStreamedState.
StateBuilder callback is triggered every time new data appears in the stream.
testWidgets(
'TextfieldStreamBuilder content test',
(WidgetTester tester) async {
final testData = TextFieldStreamedState('test');
final textFieldStateBuilder = TextFieldStateBuilder(
state: testData,
stateBuilder: (context, data) {
return Text('test');
});
await tester.pumpWidget(
MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: textFieldStateBuilder,
),
),
);
final textFinder = find.text('test');
expect(textFinder, findsOneWidget);
},
);
State #
StreamedState #
A state of some type wrapped in a stream dictates the widget's state
yourStreamedState.accept(someData);
...
StreamedStateBuilder<T>(
streamedState: yourStreamedState,
builder: (ctx, T data) => Text(data.toString()),
);
EntityStreamedState #
A state that have download/error/content status
dataState.loading();
try {
var content = await someRepository.getData();
dataState.content(content);
} catch (e) {
dataState.error(e);
}
...
EntityStateBuilder<Data>(
streamedState: dataState,
child: (data) => DataWidget(data),
loadingChild: LoadingWidget(),
errorChild: ErrorPlaceholder(),
);
Installation #
Add relation
to your pubspec.yaml
file:
dependencies:
relation: ^3.0.0
You can use both stable
and dev
versions of the package listed above in the badges bar.
Changelog #
All notable changes to this project will be documented in this file.
Issues #
For issues, file directly in the main SurfGear repo.
Contribute #
If you would like to contribute to the package (e.g. by improving the documentation, solving a bug or adding a cool new feature), please review our contribution guide first and send us your pull request.
Your PRs are always welcome.
How to reach us #
Please feel free to ask any questions about this package. Join our community chat on Telegram. We speak English and Russian.