diff --git a/integration_test/unreadmarker_test.dart b/integration_test/unreadmarker_test.dart index a63b0d7c21..c13f83f36c 100644 --- a/integration_test/unreadmarker_test.dart +++ b/integration_test/unreadmarker_test.dart @@ -40,7 +40,7 @@ void main() { child: PerAccountStoreWidget( accountId: eg.selfAccount.id, placeholder: const LoadingPlaceholderPage(), - child: const MessageListPage(narrow: AllMessagesNarrow()))))); + child: const MessageListPage(narrow: CombinedFeedNarrow()))))); await tester.pumpAndSettle(); return messages; } diff --git a/lib/model/message_list.dart b/lib/model/message_list.dart index f0d48368d0..3dce9ac584 100644 --- a/lib/model/message_list.dart +++ b/lib/model/message_list.dart @@ -332,7 +332,7 @@ class MessageListView with ChangeNotifier, _MessageSequence { /// See also [_allMessagesVisible]. bool _messageVisible(Message message) { switch (narrow) { - case AllMessagesNarrow(): + case CombinedFeedNarrow(): return switch (message) { StreamMessage() => store.isTopicVisible(message.streamId, message.subject), @@ -355,7 +355,7 @@ class MessageListView with ChangeNotifier, _MessageSequence { /// This is useful for an optimization. bool get _allMessagesVisible { switch (narrow) { - case AllMessagesNarrow(): + case CombinedFeedNarrow(): case StreamNarrow(): return false; diff --git a/lib/model/narrow.dart b/lib/model/narrow.dart index 926406bd29..d68c876190 100644 --- a/lib/model/narrow.dart +++ b/lib/model/narrow.dart @@ -39,13 +39,12 @@ sealed class SendableNarrow extends Narrow { MessageDestination get destination; } -/// The narrow called "All messages" in the UI. +/// The narrow called "Combined feed" in the UI. /// -/// This does not literally mean all messages, or even all messages -/// that the user has access to: in particular it excludes muted streams -/// and topics. -class AllMessagesNarrow extends Narrow { - const AllMessagesNarrow(); +/// All messages the user has access to, excluding unsubscribed streams +/// and muted streams and topics. See [PerAccountStore.isTopicVisible]. +class CombinedFeedNarrow extends Narrow { + const CombinedFeedNarrow(); @override bool containsMessage(Message message) { @@ -57,13 +56,13 @@ class AllMessagesNarrow extends Narrow { @override bool operator ==(Object other) { - if (other is! AllMessagesNarrow) return false; + if (other is! CombinedFeedNarrow) return false; // Conceptually there's only one value of this type. return true; } @override - int get hashCode => 'AllMessagesNarrow'.hashCode; + int get hashCode => 'CombinedFeedNarrow'.hashCode; } class StreamNarrow extends Narrow { diff --git a/lib/model/unreads.dart b/lib/model/unreads.dart index 920823e98d..9de2d70e79 100644 --- a/lib/model/unreads.dart +++ b/lib/model/unreads.dart @@ -129,7 +129,7 @@ class Unreads extends ChangeNotifier { final int selfUserId; // TODO(#370): maintain this count incrementally, rather than recomputing from scratch - int countInAllMessagesNarrow() { + int countInCombinedFeedNarrow() { int c = 0; for (final messageIds in dms.values) { c = c + messageIds.length; @@ -195,8 +195,8 @@ class Unreads extends ChangeNotifier { int countInNarrow(Narrow narrow) { switch (narrow) { - case AllMessagesNarrow(): - return countInAllMessagesNarrow(); + case CombinedFeedNarrow(): + return countInCombinedFeedNarrow(); case StreamNarrow(): return countInStreamNarrow(narrow.streamId); case TopicNarrow(): diff --git a/lib/widgets/app.dart b/lib/widgets/app.dart index 0e833e471f..5f152dc6e3 100644 --- a/lib/widgets/app.dart +++ b/lib/widgets/app.dart @@ -271,7 +271,7 @@ class HomePage extends StatelessWidget { ElevatedButton( onPressed: () => Navigator.push(context, MessageListPage.buildRoute(context: context, - narrow: const AllMessagesNarrow())), + narrow: const CombinedFeedNarrow())), child: Text(zulipLocalizations.combinedFeedPageTitle)), const SizedBox(height: 16), ElevatedButton( diff --git a/lib/widgets/compose_box.dart b/lib/widgets/compose_box.dart index c45dc0ed7a..b187019490 100644 --- a/lib/widgets/compose_box.dart +++ b/lib/widgets/compose_box.dart @@ -966,7 +966,7 @@ class ComposeBox extends StatelessWidget { return _FixedDestinationComposeBox(key: controllerKey, narrow: narrow); } else if (narrow is DmNarrow) { return _FixedDestinationComposeBox(key: controllerKey, narrow: narrow); - } else if (narrow is AllMessagesNarrow) { + } else if (narrow is CombinedFeedNarrow) { return const SizedBox.shrink(); } else { throw Exception("impossible narrow"); // TODO(dart-3): show this statically diff --git a/lib/widgets/message_list.dart b/lib/widgets/message_list.dart index 38544a0a82..58da8fc4f8 100644 --- a/lib/widgets/message_list.dart +++ b/lib/widgets/message_list.dart @@ -61,7 +61,7 @@ class _MessageListPageState extends State { final Color? appBarBackgroundColor; bool removeAppBarBottomBorder = false; switch(widget.narrow) { - case AllMessagesNarrow(): + case CombinedFeedNarrow(): appBarBackgroundColor = null; // i.e., inherit case StreamNarrow(:final streamId): @@ -106,7 +106,7 @@ class _MessageListPageState extends State { // if those details get complicated, refactor to avoid copying. // TODO(#311) If we have a bottom nav, it will pad the bottom // inset, and this should always be true. - removeBottom: widget.narrow is! AllMessagesNarrow, + removeBottom: widget.narrow is! CombinedFeedNarrow, child: Expanded( child: MessageList(narrow: widget.narrow))), @@ -142,7 +142,7 @@ class MessageListAppBarTitle extends StatelessWidget { final zulipLocalizations = ZulipLocalizations.of(context); switch (narrow) { - case AllMessagesNarrow(): + case CombinedFeedNarrow(): return Text(zulipLocalizations.combinedFeedPageTitle); case StreamNarrow(:var streamId): @@ -327,7 +327,7 @@ class _MessageListState extends State with PerAccountStoreAwareStat // The keys are of type [ValueKey] with a value of [Message.id] // and here we use a O(log n) binary search method. This could // be improved but for now it only triggers for materialized - // widgets. As a simple test, flinging through All Messages in + // widgets. As a simple test, flinging through Combined feed in // CZO on a Pixel 5, this only runs about 10 times per rebuild // and the timing for each call is <100 microseconds. // @@ -447,7 +447,7 @@ class MarkAsReadWidget extends StatelessWidget { return; } if (!context.mounted) return; - if (narrow is AllMessagesNarrow && !useLegacy) { + if (narrow is CombinedFeedNarrow && !useLegacy) { PerAccountStoreWidget.of(context).unreads.handleAllMessagesReadSuccess(); } } @@ -507,7 +507,7 @@ class RecipientHeader extends StatelessWidget { final message = this.message; return switch (message) { StreamMessage() => StreamMessageRecipientHeader(message: message, - showStream: narrow is AllMessagesNarrow), + showStream: narrow is CombinedFeedNarrow), DmMessage() => DmRecipientHeader(message: message), }; } @@ -1081,7 +1081,7 @@ Future _legacyMarkNarrowAsRead(BuildContext context, Narrow narrow) async final store = PerAccountStoreWidget.of(context); final connection = store.connection; switch (narrow) { - case AllMessagesNarrow(): + case CombinedFeedNarrow(): await markAllAsRead(connection); case StreamNarrow(:final streamId): await markStreamAsRead(connection, streamId: streamId); diff --git a/test/api/route/messages_test.dart b/test/api/route/messages_test.dart index 9e93791e90..1156fa91da 100644 --- a/test/api/route/messages_test.dart +++ b/test/api/route/messages_test.dart @@ -180,7 +180,7 @@ void main() { check(jsonEncode(narrow)).equals(expected); } - checkNarrow(const AllMessagesNarrow().apiEncode(), jsonEncode([])); + checkNarrow(const CombinedFeedNarrow().apiEncode(), jsonEncode([])); checkNarrow(const StreamNarrow(12).apiEncode(), jsonEncode([ {'operator': 'stream', 'operand': 12}, ])); @@ -246,7 +246,7 @@ void main() { return FakeApiConnection.with_((connection) async { connection.prepare(json: fakeResult.toJson()); await checkGetMessages(connection, - narrow: const AllMessagesNarrow().apiEncode(), + narrow: const CombinedFeedNarrow().apiEncode(), anchor: AnchorCode.newest, numBefore: 10, numAfter: 20, expected: { 'narrow': jsonEncode([]), @@ -278,7 +278,7 @@ void main() { return FakeApiConnection.with_((connection) async { connection.prepare(json: fakeResult.toJson()); await checkGetMessages(connection, - narrow: const AllMessagesNarrow().apiEncode(), + narrow: const CombinedFeedNarrow().apiEncode(), anchor: const NumericAnchor(42), numBefore: 10, numAfter: 20, expected: { @@ -582,7 +582,7 @@ void main() { await checkUpdateMessageFlagsForNarrow(connection, anchor: AnchorCode.oldest, numBefore: 0, numAfter: 20, - narrow: const AllMessagesNarrow().apiEncode(), + narrow: const CombinedFeedNarrow().apiEncode(), op: UpdateMessageFlagsOp.add, flag: MessageFlag.read, expected: { 'anchor': 'oldest', @@ -622,7 +622,7 @@ void main() { await checkUpdateMessageFlagsForNarrow(connection, anchor: const NumericAnchor(42), numBefore: 0, numAfter: 20, - narrow: const AllMessagesNarrow().apiEncode(), + narrow: const CombinedFeedNarrow().apiEncode(), op: UpdateMessageFlagsOp.add, flag: MessageFlag.read, expected: { 'anchor': '42', diff --git a/test/model/autocomplete_test.dart b/test/model/autocomplete_test.dart index 186299a51b..41f49d1440 100644 --- a/test/model/autocomplete_test.dart +++ b/test/model/autocomplete_test.dart @@ -166,7 +166,7 @@ void main() { }); test('MentionAutocompleteView misc', () async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); final store = eg.store(); await store.addUsers([eg.selfUser, eg.otherUser, eg.thirdUser]); final view = MentionAutocompleteView.init(store: store, narrow: narrow); @@ -183,7 +183,7 @@ void main() { test('MentionAutocompleteView not starve timers', () { fakeAsync((binding) async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); final store = eg.store(); await store.addUsers([eg.selfUser, eg.otherUser, eg.thirdUser]); final view = MentionAutocompleteView.init(store: store, narrow: narrow); @@ -218,7 +218,7 @@ void main() { }); test('MentionAutocompleteView yield between batches of 1000', () async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); final store = eg.store(); for (int i = 0; i < 2500; i++) { await store.addUser(eg.user(userId: i, email: 'user$i@example.com', fullName: 'User $i')); @@ -241,7 +241,7 @@ void main() { }); test('MentionAutocompleteView new query during computation replaces old', () async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); final store = eg.store(); for (int i = 0; i < 1500; i++) { await store.addUser(eg.user(userId: i, email: 'user$i@example.com', fullName: 'User $i')); @@ -275,7 +275,7 @@ void main() { }); test('MentionAutocompleteView mutating store.users while in progress causes retry', () async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); final store = eg.store(); for (int i = 0; i < 1500; i++) { await store.addUser(eg.user(userId: i, email: 'user$i@example.com', fullName: 'User $i')); diff --git a/test/model/compose_test.dart b/test/model/compose_test.dart index f8c81c39d4..1a56a839f3 100644 --- a/test/model/compose_test.dart +++ b/test/model/compose_test.dart @@ -223,11 +223,11 @@ hello }); group('narrowLink', () { - test('AllMessagesNarrow', () { + test('CombinedFeedNarrow', () { final store = eg.store(); - check(narrowLink(store, const AllMessagesNarrow())) + check(narrowLink(store, const CombinedFeedNarrow())) .equals(store.realmUrl.resolve('#narrow')); - check(narrowLink(store, const AllMessagesNarrow(), nearMessageId: 1)) + check(narrowLink(store, const CombinedFeedNarrow(), nearMessageId: 1)) .equals(store.realmUrl.resolve('#narrow/near/1')); }); diff --git a/test/model/message_list_test.dart b/test/model/message_list_test.dart index 181205c743..3ba9d49c3f 100644 --- a/test/model/message_list_test.dart +++ b/test/model/message_list_test.dart @@ -36,7 +36,7 @@ void main() async { void checkNotifiedOnce() => checkNotified(count: 1); /// Initialize [model] and the rest of the test state. - Future prepare({Narrow narrow = const AllMessagesNarrow()}) async { + Future prepare({Narrow narrow = const CombinedFeedNarrow()}) async { final stream = eg.stream(); subscription = eg.subscription(stream); store = eg.store(); @@ -87,7 +87,7 @@ void main() async { } test('fetchInitial', () async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); await prepare(narrow: narrow); connection.prepare(json: newestResult( foundOldest: false, @@ -140,7 +140,7 @@ void main() async { }); test('fetchOlder', () async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); await prepare(narrow: narrow); await prepareMessages(foundOldest: false, messages: List.generate(100, (i) => eg.streamMessage(id: 1000 + i))); @@ -168,7 +168,7 @@ void main() async { }); test('fetchOlder nop when already fetching', () async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); await prepare(narrow: narrow); await prepareMessages(foundOldest: false, messages: List.generate(100, (i) => eg.streamMessage(id: 1000 + i))); @@ -198,7 +198,7 @@ void main() async { }); test('fetchOlder nop when already haveOldest true', () async { - await prepare(narrow: const AllMessagesNarrow()); + await prepare(narrow: const CombinedFeedNarrow()); await prepareMessages(foundOldest: true, messages: List.generate(30, (i) => eg.streamMessage())); check(model) @@ -216,7 +216,7 @@ void main() async { }); test('fetchOlder handles servers not understanding includeAnchor', () async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); await prepare(narrow: narrow); await prepareMessages(foundOldest: false, messages: List.generate(100, (i) => eg.streamMessage(id: 1000 + i))); @@ -555,10 +555,10 @@ void main() async { }); group('stream/topic muting', () { - test('in AllMessagesNarrow', () async { + test('in CombinedFeedNarrow', () async { final stream1 = eg.stream(streamId: 1, name: 'stream 1'); final stream2 = eg.stream(streamId: 2, name: 'stream 2'); - await prepare(narrow: const AllMessagesNarrow()); + await prepare(narrow: const CombinedFeedNarrow()); await store.addStreams([stream1, stream2]); await store.addSubscription(eg.subscription(stream1)); await store.addUserTopic(stream1, 'B', UserTopicVisibilityPolicy.muted); @@ -923,7 +923,7 @@ void checkInvariants(MessageListView model) { if (message is! StreamMessage) continue; switch (model.narrow) { - case AllMessagesNarrow(): + case CombinedFeedNarrow(): check(model.store.isTopicVisible(message.streamId, message.subject)) .isTrue(); case StreamNarrow(): diff --git a/test/model/unreads_test.dart b/test/model/unreads_test.dart index ad097b08e2..ce1e16178d 100644 --- a/test/model/unreads_test.dart +++ b/test/model/unreads_test.dart @@ -152,7 +152,7 @@ void main() { }); group('count helpers', () { - test('countInAllMessagesNarrow', () async { + test('countInCombinedFeedNarrow', () async { final stream1 = eg.stream(streamId: 1, name: 'stream 1'); final stream2 = eg.stream(streamId: 2, name: 'stream 2'); final stream3 = eg.stream(streamId: 3, name: 'stream 3'); @@ -171,7 +171,7 @@ void main() { eg.dmMessage(from: eg.otherUser, to: [eg.selfUser], flags: []), eg.dmMessage(from: eg.thirdUser, to: [eg.selfUser], flags: []), ]); - check(model.countInAllMessagesNarrow()).equals(5); + check(model.countInCombinedFeedNarrow()).equals(5); }); test('countInStream/Narrow', () async { diff --git a/test/widgets/action_sheet_test.dart b/test/widgets/action_sheet_test.dart index 6f2933cc5c..a006fa640f 100644 --- a/test/widgets/action_sheet_test.dart +++ b/test/widgets/action_sheet_test.dart @@ -442,9 +442,9 @@ void main() { )); }); - testWidgets('not offered in AllMessagesNarrow (composing to reply is not yet supported)', (WidgetTester tester) async { + testWidgets('not offered in CombinedFeedNarrow (composing to reply is not yet supported)', (WidgetTester tester) async { final message = eg.streamMessage(); - await setupToMessageActionSheet(tester, message: message, narrow: const AllMessagesNarrow()); + await setupToMessageActionSheet(tester, message: message, narrow: const CombinedFeedNarrow()); check(findQuoteAndReplyButton(tester)).isNull(); }); }); diff --git a/test/widgets/message_list_test.dart b/test/widgets/message_list_test.dart index 425f1338c4..c78cd68aa7 100644 --- a/test/widgets/message_list_test.dart +++ b/test/widgets/message_list_test.dart @@ -41,7 +41,7 @@ void main() { late FakeApiConnection connection; Future setupMessageListPage(WidgetTester tester, { - Narrow narrow = const AllMessagesNarrow(), + Narrow narrow = const CombinedFeedNarrow(), bool foundOldest = true, int? messageCount, List? messages, @@ -248,9 +248,9 @@ void main() { matching: find.text(text)).evaluate(); } - testWidgets('show stream name in AllMessagesNarrow', (tester) async { + testWidgets('show stream name in CombinedFeedNarrow', (tester) async { await setupMessageListPage(tester, - narrow: const AllMessagesNarrow(), + narrow: const CombinedFeedNarrow(), messages: [message], subscriptions: [eg.subscription(stream)]); await tester.pump(); check(findInMessageList('stream name')).length.equals(1); @@ -340,12 +340,12 @@ void main() { testWidgets('show stream name from message when stream unknown', (tester) async { // This can perfectly well happen, because message fetches can race // with events. - // … Though not actually with AllMessagesNarrow, because that shows + // … Though not actually with CombinedFeedNarrow, because that shows // stream messages only in subscribed streams, hence only known streams. // See skip comment below. final stream = eg.stream(name: 'stream name'); await setupMessageListPage(tester, - narrow: const AllMessagesNarrow(), + narrow: const CombinedFeedNarrow(), subscriptions: [], messages: [ eg.streamMessage(stream: stream), @@ -362,7 +362,7 @@ void main() { 'name': 'new stream name', }); await setupMessageListPage(tester, - narrow: const AllMessagesNarrow(), + narrow: const CombinedFeedNarrow(), subscriptions: [eg.subscription(streamAfter)], messages: [ eg.streamMessage(stream: streamBefore), @@ -765,7 +765,7 @@ void main() { }); testWidgets('markAllMessagesAsRead uses is:unread optimization', (WidgetTester tester) async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); await setupMessageListPage(tester, narrow: narrow, messages: [message], unreadMsgs: unreadMsgs); check(isMarkAsReadButtonVisible(tester)).isTrue(); @@ -839,7 +839,7 @@ void main() { }); testWidgets('markNarrowAsRead on mark-all-as-read when Unreads.oldUnreadsMissing: true', (tester) async { - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); await setupMessageListPage(tester, narrow: narrow, messages: [message], unreadMsgs: unreadMsgs); check(isMarkAsReadButtonVisible(tester)).isTrue(); @@ -886,8 +886,8 @@ void main() { expectedMessage: zulipLocalizations.errorInvalidResponse); }); - testWidgets('AllMessagesNarrow on legacy server', (WidgetTester tester) async { - const narrow = AllMessagesNarrow(); + testWidgets('CombinedFeedNarrow on legacy server', (WidgetTester tester) async { + const narrow = CombinedFeedNarrow(); await setupMessageListPage(tester, narrow: narrow, messages: [message], unreadMsgs: unreadMsgs); check(isMarkAsReadButtonVisible(tester)).isTrue(); @@ -978,7 +978,7 @@ void main() { testWidgets('catch-all api errors', (WidgetTester tester) async { final zulipLocalizations = GlobalLocalizations.zulipLocalizations; - const narrow = AllMessagesNarrow(); + const narrow = CombinedFeedNarrow(); await setupMessageListPage(tester, narrow: narrow, messages: [message], unreadMsgs: unreadMsgs); check(isMarkAsReadButtonVisible(tester)).isTrue();