Skip to content

Commit 2a6a504

Browse files
committed
api: Implement TopicName.isSameAs(other) and .unresolve()
1 parent a7955ca commit 2a6a504

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

lib/api/model/model.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,14 @@ extension type const TopicName(String _value) {
669669
// https://github.com/zulip/zulip/blob/1fac99733/web/shared/src/resolved_topic.ts
670670
static const resolvedTopicPrefix = '✔ ';
671671

672+
/// Pattern for an arbitrary resolved-topic prefix.
673+
///
674+
/// These always begin with [resolvedTopicPrefix]
675+
/// but can be weird and go on longer, like "✔ ✔✔ ".
676+
// This is RESOLVED_TOPIC_PREFIX_RE in web:
677+
// https://github.com/zulip/zulip/blob/1fac99733/web/shared/src/resolved_topic.ts#L4-L12
678+
static final resolvedTopicPrefixRegexp = RegExp(r'^✔ [ ✔]*');
679+
672680
/// The string this topic is identified by in the Zulip API.
673681
///
674682
/// This should be used in constructing HTTP requests to the server,
@@ -687,6 +695,14 @@ extension type const TopicName(String _value) {
687695
/// The key to use for "same topic as" comparisons.
688696
String canonicalize() => apiName.toLowerCase();
689697

698+
/// A [TopicName] with [resolvedTopicPrefixRegexp] stripped if present.
699+
TopicName unresolve() =>
700+
TopicName(_value.replaceFirst(resolvedTopicPrefixRegexp, ''));
701+
702+
/// Whether [this] and [other] have the same canonical form,
703+
/// using [canonicalize].
704+
bool isSameAs(TopicName other) => canonicalize() == other.canonicalize();
705+
690706
TopicName.fromJson(this._value);
691707

692708
String toJson() => apiName;

test/api/model/model_test.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,43 @@ void main() {
126126
// MessageEditState group.
127127
});
128128

129+
group('TopicName', () {
130+
test('unresolve', () {
131+
void doCheck(TopicName input, TopicName expected) {
132+
final output = input.unresolve();
133+
check(output).apiName.equals(expected.apiName);
134+
}
135+
136+
doCheck(eg.t('some topic'), eg.t('some topic'));
137+
doCheck(eg.t('Some Topic'), eg.t('Some Topic'));
138+
doCheck(eg.t('✔ some topic'), eg.t('some topic'));
139+
doCheck(eg.t('✔ Some Topic'), eg.t('Some Topic'));
140+
141+
doCheck(eg.t('Some ✔ Topic'), eg.t('Some ✔ Topic'));
142+
doCheck(eg.t('✔ Some ✔ Topic'), eg.t('Some ✔ Topic'));
143+
144+
doCheck(eg.t('✔ ✔✔✔ some topic'), eg.t('some topic'));
145+
doCheck(eg.t('✔ ✔ ✔✔some topic'), eg.t('some topic'));
146+
});
147+
148+
test('isSameAs', () {
149+
void doCheck(TopicName topicA, TopicName topicB, bool expected) {
150+
check(topicA.isSameAs(topicB)).equals(expected);
151+
}
152+
153+
doCheck(eg.t('some topic'), eg.t('some topic'), true);
154+
doCheck(eg.t('SOME TOPIC'), eg.t('SOME TOPIC'), true);
155+
doCheck(eg.t('Some Topic'), eg.t('sOME tOPIC'), true);
156+
doCheck(eg.t('✔ a'), eg.t('✔ a'), true);
157+
158+
doCheck(eg.t('✔ some topic'), eg.t('some topic'), false);
159+
doCheck(eg.t('SOME TOPIC'), eg.t('✔ SOME TOPIC'), false);
160+
doCheck(eg.t('✔ Some Topic'), eg.t('sOME tOPIC'), false);
161+
162+
doCheck(eg.t('✔ a'), eg.t('✔ b'), false);
163+
});
164+
});
165+
129166
group('DmMessage', () {
130167
final Map<String, dynamic> baseJson = Map.unmodifiable(deepToJson(
131168
eg.dmMessage(from: eg.otherUser, to: [eg.selfUser]),

0 commit comments

Comments
 (0)