Skip to content

Commit a20bddc

Browse files
Sharath S RSharath S R
authored andcommitted
feat(networkWidget): added loader and error widget support to network widget
1 parent 36c3b60 commit a20bddc

File tree

6 files changed

+228
-2
lines changed

6 files changed

+228
-2
lines changed

examples/stac_gallery/assets/json/home_screen.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,5 +1440,27 @@
14401440
"assetPath": "assets/json/backdrop_filter_example.json"
14411441
}
14421442
}
1443+
},
1444+
{
1445+
"type": "listTile",
1446+
"leading": {
1447+
"type": "icon",
1448+
"icon": "cloud_download"
1449+
},
1450+
"title": {
1451+
"type": "text",
1452+
"data": "Stac Network Widget"
1453+
},
1454+
"subtitle": {
1455+
"type": "text",
1456+
"data": "Fetch data from network with loading and error states"
1457+
},
1458+
"onTap": {
1459+
"actionType": "navigate",
1460+
"widgetJson": {
1461+
"type": "exampleScreen",
1462+
"assetPath": "assets/json/network_widget_example.json"
1463+
}
1464+
}
14431465
}
14441466
]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
{
2+
"type": "scaffold",
3+
"appBar": {
4+
"type": "appBar",
5+
"title": {
6+
"type": "text",
7+
"data": "Network Widget Example"
8+
}
9+
},
10+
"body": {
11+
"type": "networkWidget",
12+
"request": {
13+
"actionType": "networkRequest",
14+
"url": "https://httpbin.org/delay/2",
15+
"method": "get"
16+
},
17+
"loadingWidget": {
18+
"type": "center",
19+
"child": {
20+
"type": "column",
21+
"mainAxisAlignment": "center",
22+
"children": [
23+
{
24+
"type": "circularProgressIndicator"
25+
},
26+
{
27+
"type": "sizedBox",
28+
"height": 16.0
29+
},
30+
{
31+
"type": "text",
32+
"data": "Loading..."
33+
}
34+
]
35+
}
36+
},
37+
"errorWidget": {
38+
"type": "center",
39+
"child": {
40+
"type": "column",
41+
"mainAxisAlignment": "center",
42+
"children": [
43+
{
44+
"type": "icon",
45+
"icon": "error",
46+
"size": 48.0,
47+
"color": "#E53935"
48+
},
49+
{
50+
"type": "sizedBox",
51+
"height": 16.0
52+
},
53+
{
54+
"type": "text",
55+
"data": "Failed to load",
56+
"style": {
57+
"fontSize": 18.0,
58+
"fontWeight": "bold"
59+
}
60+
},
61+
{
62+
"type": "sizedBox",
63+
"height": 8.0
64+
},
65+
{
66+
"type": "text",
67+
"data": "Please check your connection and try again"
68+
}
69+
]
70+
}
71+
}
72+
}
73+
}
74+

packages/stac/lib/src/parsers/widgets/stac_network_widget/stac_network_widget_parser.dart

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,23 @@ class StacNetworkWidgetParser extends StacParser<StacNetworkWidget> {
1515

1616
@override
1717
Widget parse(BuildContext context, StacNetworkWidget model) {
18-
return Stac.fromNetwork(context: context, request: model.request);
18+
return Stac.fromNetwork(
19+
context: context,
20+
request: model.request,
21+
loadingWidget: model.loadingWidget == null
22+
? null
23+
: (ctx) => StacService.fromStacWidget(
24+
widget: model.loadingWidget!,
25+
context: ctx,
26+
) ??
27+
const SizedBox(),
28+
errorWidget: model.errorWidget == null
29+
? null
30+
: (ctx, error) => StacService.fromStacWidget(
31+
widget: model.errorWidget!,
32+
context: ctx,
33+
) ??
34+
const SizedBox(),
35+
);
1936
}
2037
}

packages/stac_core/lib/widgets/network_widget/stac_network_widget.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,21 @@ part 'stac_network_widget.g.dart';
3838
@JsonSerializable()
3939
class StacNetworkWidget extends StacWidget {
4040
/// Creates a [StacNetworkWidget].
41-
const StacNetworkWidget({required this.request});
41+
const StacNetworkWidget({
42+
required this.request,
43+
this.loadingWidget,
44+
this.errorWidget,
45+
});
4246

4347
/// The network request to execute.
4448
final StacNetworkRequest request;
4549

50+
/// Optional widget to render while the network request is in progress.
51+
final StacWidget? loadingWidget;
52+
53+
/// Optional widget to render if the network request fails.
54+
final StacWidget? errorWidget;
55+
4656
/// Widget type identifier.
4757
@override
4858
String get type => WidgetType.networkWidget.name;

packages/stac_core/lib/widgets/network_widget/stac_network_widget.g.dart

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:stac_core/stac_core.dart';
3+
4+
void main() {
5+
group('StacNetworkWidget', () {
6+
test('should create from JSON with loadingWidget and errorWidget', () {
7+
// Arrange
8+
const json = {
9+
'type': 'networkWidget',
10+
'request': {
11+
'actionType': 'networkRequest',
12+
'url': 'https://example.com/data',
13+
'method': 'get'
14+
},
15+
'loadingWidget': {
16+
'type': 'text',
17+
'data': 'Loading...'
18+
},
19+
'errorWidget': {
20+
'type': 'text',
21+
'data': 'Error occurred'
22+
}
23+
};
24+
25+
// Act
26+
final widget = StacNetworkWidget.fromJson(json);
27+
28+
// Assert
29+
expect(widget.request.url, equals('https://example.com/data'));
30+
expect(widget.loadingWidget, isNotNull);
31+
expect(widget.errorWidget, isNotNull);
32+
});
33+
34+
test('should create from JSON without optional widgets', () {
35+
// Arrange
36+
const json = {
37+
'type': 'networkWidget',
38+
'request': {
39+
'actionType': 'networkRequest',
40+
'url': 'https://example.com/data',
41+
'method': 'get'
42+
}
43+
};
44+
45+
// Act
46+
final widget = StacNetworkWidget.fromJson(json);
47+
48+
// Assert
49+
expect(widget.request.url, equals('https://example.com/data'));
50+
expect(widget.loadingWidget, isNull);
51+
expect(widget.errorWidget, isNull);
52+
});
53+
54+
test('should serialize to JSON with loadingWidget and errorWidget', () {
55+
// Arrange
56+
final widget = StacNetworkWidget(
57+
request: StacNetworkRequest(
58+
url: 'https://example.com/data',
59+
method: 'get',
60+
),
61+
loadingWidget: StacWidget.fromJson({'type': 'text', 'data': 'Loading...'}),
62+
errorWidget: StacWidget.fromJson({'type': 'text', 'data': 'Error'}),
63+
);
64+
65+
// Act
66+
final json = widget.toJson();
67+
68+
// Assert
69+
expect(json['request'], isNotNull);
70+
expect(json['loadingWidget'], isNotNull);
71+
expect(json['errorWidget'], isNotNull);
72+
expect(json['loadingWidget']['data'], equals('Loading...'));
73+
expect(json['errorWidget']['data'], equals('Error'));
74+
});
75+
76+
test('should serialize to JSON without optional widgets', () {
77+
// Arrange
78+
final widget = StacNetworkWidget(
79+
request: StacNetworkRequest(
80+
url: 'https://example.com/data',
81+
method: 'get',
82+
),
83+
);
84+
85+
// Act
86+
final json = widget.toJson();
87+
88+
// Assert
89+
expect(json['request'], isNotNull);
90+
expect(json['loadingWidget'], isNull);
91+
expect(json['errorWidget'], isNull);
92+
});
93+
});
94+
}
95+

0 commit comments

Comments
 (0)