Skip to content

Commit c2ca04d

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

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
@@ -507,10 +507,9 @@ class MarkAsReadWidgetState extends State<MarkAsReadWidget> {
507507

508508
return IgnorePointer(
509509
ignoring: areMessagesRead,
510-
child: AnimatedOpacity(
511-
opacity: areMessagesRead ? 0 : loading ? 0.5 : 1,
512-
duration: Duration(milliseconds: areMessagesRead ? 2000 : 300),
513-
curve: Curves.easeOut,
510+
child: MarkAsReadAnimation(
511+
loading: loading,
512+
hidden: areMessagesRead,
514513
child: SizedBox(width: double.infinity,
515514
// Design referenced from:
516515
// https://www.figma.com/file/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?type=design&node-id=132-9684&mode=design&t=jJwHzloKJ0TMOG4M-0
@@ -544,6 +543,28 @@ class MarkAsReadWidgetState extends State<MarkAsReadWidget> {
544543
}
545544
}
546545

546+
class MarkAsReadAnimation extends StatelessWidget {
547+
final bool loading;
548+
final bool hidden;
549+
final Widget child;
550+
551+
const MarkAsReadAnimation({
552+
super.key,
553+
required this.loading,
554+
required this.hidden,
555+
required this.child
556+
});
557+
558+
@override
559+
Widget build(BuildContext context) {
560+
return AnimatedOpacity(
561+
opacity: hidden ? 0 : loading ? 0.5 : 1,
562+
duration: const Duration(milliseconds: 500),
563+
curve: Curves.easeOut,
564+
child: child);
565+
}
566+
}
567+
547568
class RecipientHeader extends StatelessWidget {
548569
const RecipientHeader({super.key, required this.message, required this.narrow});
549570

test/widgets/message_list_test.dart

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

949949
check(state.loading).isFalse();
950950
});
951+
952+
testWidgets('in idle state', (WidgetTester tester) async {
953+
final child = Container();
954+
955+
await tester.pumpWidget(MaterialApp(
956+
home: MarkAsReadAnimation(hidden: false, loading: false, child: child)));
957+
958+
check(find.byWidget(child).evaluate()).length.equals(1);
959+
check(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).opacity).equals(1);
960+
});
961+
962+
testWidgets('in loading state', (WidgetTester tester) async {
963+
final child = Container();
964+
965+
await tester.pumpWidget(MaterialApp(
966+
home: MarkAsReadAnimation(hidden: false, loading: true, child: child)));
967+
968+
check(find.byWidget(child).evaluate()).length.equals(1);
969+
check(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).opacity).equals(0.5);
970+
});
971+
972+
testWidgets('in hidden state', (WidgetTester tester) async {
973+
final child = Container();
974+
975+
await tester.pumpWidget(MaterialApp(
976+
home: MarkAsReadAnimation(hidden: true, loading: false, child: child)));
977+
978+
check(find.byWidget(child).evaluate()).length.equals(1);
979+
check(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).opacity).equals(0);
980+
});
981+
982+
testWidgets('in hidden state but loading is true', (WidgetTester tester) async {
983+
final child = Container();
984+
985+
await tester.pumpWidget(MaterialApp(
986+
home: MarkAsReadAnimation(hidden: true, loading: true, child: child)));
987+
988+
check(find.byWidget(child).evaluate()).length.equals(1);
989+
check(tester.widget<AnimatedOpacity>(find.byType(AnimatedOpacity)).opacity).equals(0);
990+
});
951991
});
952992

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

0 commit comments

Comments
 (0)