diff --git a/lib/widgets/subscription_list.dart b/lib/widgets/subscription_list.dart index d2faf03b2c..07f9b84c4a 100644 --- a/lib/widgets/subscription_list.dart +++ b/lib/widgets/subscription_list.dart @@ -41,10 +41,22 @@ class _SubscriptionListPageBodyState extends State wit }); } + static 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..a3fc13dac9 100644 --- a/test/widgets/subscription_list_test.dart +++ b/test/widgets/subscription_list_test.dart @@ -150,6 +150,29 @@ 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')), + ]); + check(listedStreamIds(tester)).deepEquals([3, 2, 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 {