From 79e0820e5a6040791859b45b154e19cc40e38be1 Mon Sep 17 00:00:00 2001 From: lakshya1goel Date: Wed, 22 Jan 2025 10:22:49 +0530 Subject: [PATCH] home: Sort leading emoji first in channel names Fixes: #1202 --- lib/widgets/subscription_list.dart | 12 +++++++++++ test/widgets/subscription_list_test.dart | 26 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/lib/widgets/subscription_list.dart b/lib/widgets/subscription_list.dart index d2faf03b2c..2a0c4cc07d 100644 --- a/lib/widgets/subscription_list.dart +++ b/lib/widgets/subscription_list.dart @@ -41,10 +41,22 @@ class _SubscriptionListPageBodyState extends State wit }); } + final _startsWithEmojiRegex = RegExp(r'^\p{Emoji}', unicode: true); + void _sortSubs(List list) { list.sort((a, b) { if (a.isMuted && !b.isMuted) return 1; if (!a.isMuted && b.isMuted) return -1; + + // A user gave feedback wanting zulip-flutter to match web in putting + // emoji-prefixed channels first; see #1202. + // For matching web's ordering completely, see: + // https://github.com/zulip/zulip-flutter/issues/1165 + final aStartsWithEmoji = _startsWithEmojiRegex.hasMatch(a.name); + final bStartsWithEmoji = _startsWithEmojiRegex.hasMatch(b.name); + if (aStartsWithEmoji && !bStartsWithEmoji) return -1; + if (!aStartsWithEmoji && bStartsWithEmoji) return 1; + // TODO(i18n): add locale-aware sorting return a.name.toLowerCase().compareTo(b.name.toLowerCase()); }); diff --git a/test/widgets/subscription_list_test.dart b/test/widgets/subscription_list_test.dart index a58124a533..f1d5cbfc88 100644 --- a/test/widgets/subscription_list_test.dart +++ b/test/widgets/subscription_list_test.dart @@ -150,6 +150,32 @@ void main() { ]); check(listedStreamIds(tester)).deepEquals([2, 1, 3, 4, 6, 5]); }); + + testWidgets('channels with names starting with an emoji are above channel names that do not start with an emoji', (tester) async { + await setupStreamListPage(tester, subscriptions: [ + eg.subscription(eg.stream(streamId: 1, name: 'Happy 😊 Stream')), + eg.subscription(eg.stream(streamId: 2, name: 'Alpha Stream')), + eg.subscription(eg.stream(streamId: 3, name: '🚀 Rocket Stream')), + eg.subscription(eg.stream(streamId: 4, name: 'Beta Stream')), + ]); + + check(listedStreamIds(tester)).deepEquals([3, 2, 4, 1]); + }); + + testWidgets('channels with names starting with an emoji, pinned, unpinned, muted, and unmuted are sorted correctly', (tester) async { + await setupStreamListPage(tester, subscriptions: [ + eg.subscription(eg.stream(streamId: 1, name: '😊 Happy Stream'), pinToTop: true, isMuted: false), + eg.subscription(eg.stream(streamId: 2, name: '🚀 Rocket Stream'), pinToTop: true, isMuted: true), + eg.subscription(eg.stream(streamId: 3, name: 'Alpha Stream'), pinToTop: true, isMuted: false), + eg.subscription(eg.stream(streamId: 4, name: 'Beta Stream'), pinToTop: true, isMuted: true), + eg.subscription(eg.stream(streamId: 5, name: '🌟 Star Stream'), pinToTop: false, isMuted: false), + eg.subscription(eg.stream(streamId: 6, name: '🔥 Fire Stream'), pinToTop: false, isMuted: true), + eg.subscription(eg.stream(streamId: 7, name: 'Gamma Stream'), pinToTop: false, isMuted: false), + eg.subscription(eg.stream(streamId: 8, name: 'Delta Stream'), pinToTop: false, isMuted: true), + ]); + + check(listedStreamIds(tester)).deepEquals([1, 3, 2, 4, 5, 7, 6, 8]); + }); }); testWidgets('unread badge shows with unreads', (tester) async {