Skip to content

Commit c8b18c3

Browse files
committed
feat:widget for displaying 'Connecting' snackbar
The widget, comprising a StatefulWidget (SnackBarPage) and its corresponding state class (SnackBarPageState) Previously, the absence of a dedicated mechanism to display connection-related messages resulted in users experiencing ambiguity regarding Data Staleness. By leveraging the initState and didUpdateWidget methods, the SnackBar is displayed post-build and upon isStale updates. Fixes #465
1 parent 3a2261c commit c8b18c3

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

lib/widgets/app.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'recent_dm_conversations.dart';
1616
import 'store.dart';
1717
import 'subscription_list.dart';
1818
import 'theme.dart';
19+
import 'snackbar.dart';
1920

2021
class ZulipApp extends StatefulWidget {
2122
const ZulipApp({super.key, this.navigatorObservers});
@@ -295,6 +296,10 @@ class HomePage extends StatelessWidget {
295296
MessageListPage.buildRoute(context: context,
296297
narrow: StreamNarrow(testStreamId!))),
297298
child: const Text("#test here")), // scaffolding hack, see above
299+
SizedBox(
300+
height:40,
301+
child:SnackBarPage(isStale:store.isStale),
302+
),
298303
],
299304
])));
300305
}

lib/widgets/snackbar.dart

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import 'package:flutter/material.dart';
2+
3+
class SnackBarPage extends StatefulWidget {
4+
final bool isStale;
5+
const SnackBarPage({super.key, required this.isStale});
6+
7+
@override
8+
SnackBarPageState createState() => SnackBarPageState();
9+
}
10+
11+
class SnackBarPageState extends State<SnackBarPage> {
12+
@override
13+
void initState() {
14+
super.initState();
15+
// Call showSnackBar() after the build process is complete
16+
WidgetsBinding.instance.addPostFrameCallback((_) {
17+
if (widget.isStale) {
18+
showSnackBar();
19+
}
20+
});
21+
}
22+
23+
@override
24+
void didUpdateWidget(covariant SnackBarPage oldWidget) {
25+
super.didUpdateWidget(oldWidget);
26+
// Check if isStale changed to true
27+
if (widget.isStale && !oldWidget.isStale) {
28+
WidgetsBinding.instance.addPostFrameCallback((_) {
29+
showSnackBar();
30+
});
31+
}
32+
}
33+
34+
void showSnackBar() {
35+
String snackBarText = 'Connecting';
36+
ScaffoldMessenger.of(context).showSnackBar(
37+
SnackBar(
38+
content: Row(
39+
children: [
40+
const Icon(
41+
Icons.sync,
42+
color: Colors.white,
43+
),
44+
const SizedBox(width: 8),
45+
Text(
46+
snackBarText,
47+
style: const TextStyle(color: Colors.white),
48+
)]),
49+
duration: const Duration(seconds: 20),
50+
));
51+
}
52+
53+
@override
54+
Widget build(BuildContext context) {
55+
return Container(); // Return an empty container or another widget here
56+
}
57+
}
58+
59+

test/widgets/snackbar_test.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:zulip/widgets/snackbar.dart';
4+
5+
void main() {
6+
testWidgets('Test SnackBarPage', (WidgetTester tester) async {
7+
/// SnackBarPage widget
8+
await tester.pumpWidget(
9+
const MaterialApp(
10+
home: Scaffold(
11+
body: SnackBarPage(isStale: false),
12+
),
13+
),
14+
);
15+
16+
/// noSnackBar is shown
17+
await tester.pump();
18+
expect(find.byType(SnackBar), findsNothing);
19+
20+
/// Change isStale to true
21+
await tester.pumpWidget(
22+
const MaterialApp(
23+
home: Scaffold(
24+
body: SnackBarPage(isStale: true),
25+
),
26+
),
27+
);
28+
29+
/// SnackBar is shown
30+
await tester.pump();
31+
expect(find.text('Connecting'), findsOneWidget);
32+
});
33+
}

0 commit comments

Comments
 (0)