diff --git a/lib/model/internal_link.dart b/lib/model/internal_link.dart index 4c43f83165..e933a0e6f8 100644 --- a/lib/model/internal_link.dart +++ b/lib/model/internal_link.dart @@ -154,6 +154,7 @@ Narrow? _interpretNarrowSegments(List segments, PerAccountStore store) { ApiNarrowStream? streamElement; ApiNarrowTopic? topicElement; ApiNarrowDm? dmElement; + ApiNarrowIsMentioned? isMentionedElement; for (var i = 0; i < segments.length; i += 2) { final (operator, negated) = _parseOperator(segments[i]); @@ -181,6 +182,10 @@ Narrow? _interpretNarrowSegments(List segments, PerAccountStore store) { if (dmIds == null) return null; dmElement = ApiNarrowDm(dmIds, negated: negated); + case _NarrowOperator.is_: + if (isMentionedElement != null) return null; + if (operand == 'mentioned') isMentionedElement = ApiNarrowIsMentioned(); + case _NarrowOperator.near: // TODO(#82): support for near case _NarrowOperator.with_: // TODO(#683): support for with continue; @@ -190,7 +195,10 @@ Narrow? _interpretNarrowSegments(List segments, PerAccountStore store) { } } - if (dmElement != null) { + if (isMentionedElement != null) { + if (streamElement != null || topicElement != null || dmElement != null) return null; + return const MentionsNarrow(); + } else if (dmElement != null) { if (streamElement != null || topicElement != null) return null; return DmNarrow.withUsers(dmElement.operand, selfUserId: store.selfUserId); } else if (streamElement != null) { @@ -212,6 +220,9 @@ enum _NarrowOperator { // cannot use `with` as it is a reserved keyword in Dart @JsonValue('with') with_, + // cannot use `is` as it is a reserved keyword in Dart + @JsonValue('is') + is_, pmWith, stream, channel, diff --git a/lib/model/internal_link.g.dart b/lib/model/internal_link.g.dart index 7978a3d939..5271c4a2ec 100644 --- a/lib/model/internal_link.g.dart +++ b/lib/model/internal_link.g.dart @@ -12,6 +12,7 @@ const _$_NarrowOperatorEnumMap = { _NarrowOperator.dm: 'dm', _NarrowOperator.near: 'near', _NarrowOperator.with_: 'with', + _NarrowOperator.is_: 'is', _NarrowOperator.pmWith: 'pm-with', _NarrowOperator.stream: 'stream', _NarrowOperator.channel: 'channel', diff --git a/test/model/internal_link_test.dart b/test/model/internal_link_test.dart index 117e824169..9636e6055a 100644 --- a/test/model/internal_link_test.dart +++ b/test/model/internal_link_test.dart @@ -221,6 +221,20 @@ void main() { testExpectedNarrows(testCases, streams: streams); }); + group('"/#narrow/is/mentioned returns expected MentionsNarrow', () { + final testCases = [ + ('/#narrow/is/mentioned', const MentionsNarrow()), + ('/#narrow/is/mentioned/near/1', const MentionsNarrow()), + ('/#narrow/is/mentioned/with/2', const MentionsNarrow()), + ('/#narrow/channel/7-test-here/is/mentioned', null), + ('/#narrow/channel/check/topic/test/is/mentioned', null), + ('/#narrow/topic/test/is/mentioned', null), + ('/#narrow/dm/17327-Chris-Bobbe-(Test-Account)/is/mentioned', null), + ('/#narrow/-is/mentioned', null), + ]; + testExpectedNarrows(testCases, streams: streams); + }); + group('unexpected link shapes are rejected', () { final testCases = [ ('/#narrow/stream/name/topic/', null), // missing operand