Skip to content

Commit eb73e49

Browse files
committed
msglist: Use faster fade to hidden animation for mark as read button
Fixes: zulip#613
1 parent d5d56e5 commit eb73e49

File tree

2 files changed

+65
-4
lines changed

2 files changed

+65
-4
lines changed

lib/widgets/message_list.dart

+25-4
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,9 @@ class MarkAsReadWidgetState extends State<MarkAsReadWidget> {
486486

487487
return IgnorePointer(
488488
ignoring: areMessagesRead,
489-
child: AnimatedOpacity(
490-
opacity: areMessagesRead ? 0 : loading ? 0.5 : 1,
491-
duration: Duration(milliseconds: areMessagesRead ? 2000 : 300),
492-
curve: Curves.easeOut,
489+
child: MarkAsReadAnimation(
490+
loading: loading,
491+
hidden: areMessagesRead,
493492
child: SizedBox(width: double.infinity,
494493
// Design referenced from:
495494
// https://www.figma.com/file/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?type=design&node-id=132-9684&mode=design&t=jJwHzloKJ0TMOG4M-0
@@ -523,6 +522,28 @@ class MarkAsReadWidgetState extends State<MarkAsReadWidget> {
523522
}
524523
}
525524

525+
class MarkAsReadAnimation extends StatelessWidget {
526+
final bool loading;
527+
final bool hidden;
528+
final Widget child;
529+
530+
const MarkAsReadAnimation({
531+
super.key,
532+
required this.loading,
533+
required this.hidden,
534+
required this.child
535+
});
536+
537+
@override
538+
Widget build(BuildContext context) {
539+
return AnimatedOpacity(
540+
opacity: hidden ? 0 : loading ? 0.5 : 1,
541+
duration: const Duration(milliseconds: 500),
542+
curve: Curves.easeOut,
543+
child: child);
544+
}
545+
}
546+
526547
class RecipientHeader extends StatelessWidget {
527548
const RecipientHeader({super.key, required this.message, required this.narrow});
528549

test/widgets/message_list_test.dart

+40
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,46 @@ void main() {
813813

814814
check(state.loading).isFalse();
815815
});
816+
817+
testWidgets('in idle state', (WidgetTester tester) async {
818+
final child = Container();
819+
820+
await tester.pumpWidget(MaterialApp(
821+
home: MarkAsReadAnimation(hidden: false, loading: false, child: child)));
822+
823+
check(find.byWidget(child).evaluate()).length.equals(1);
824+
check(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).opacity).equals(1);
825+
});
826+
827+
testWidgets('in loading state', (WidgetTester tester) async {
828+
final child = Container();
829+
830+
await tester.pumpWidget(MaterialApp(
831+
home: MarkAsReadAnimation(hidden: false, loading: true, child: child)));
832+
833+
check(find.byWidget(child).evaluate()).length.equals(1);
834+
check(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).opacity).equals(0.5);
835+
});
836+
837+
testWidgets('in hidden state', (WidgetTester tester) async {
838+
final child = Container();
839+
840+
await tester.pumpWidget(MaterialApp(
841+
home: MarkAsReadAnimation(hidden: true, loading: false, child: child)));
842+
843+
check(find.byWidget(child).evaluate()).length.equals(1);
844+
check(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).opacity).equals(0);
845+
});
846+
847+
testWidgets('in hidden state but loading is true', (WidgetTester tester) async {
848+
final child = Container();
849+
850+
await tester.pumpWidget(MaterialApp(
851+
home: MarkAsReadAnimation(hidden: true, loading: true, child: child)));
852+
853+
check(find.byWidget(child).evaluate()).length.equals(1);
854+
check(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).opacity).equals(0);
855+
});
816856
});
817857

818858
testWidgets('smoke test on modern server', (WidgetTester tester) async {

0 commit comments

Comments
 (0)