@@ -550,6 +550,15 @@ String? tryParseEmojiCodeToUnicode(String emojiCode) {
550
550
}
551
551
}
552
552
553
+ /// The topic servers understand to mean "there is no topic".
554
+ ///
555
+ /// This should match
556
+ /// https://github.com/zulip/zulip/blob/6.0/zerver/actions/message_edit.py#L940
557
+ /// or similar logic at the latest `main` .
558
+ // This is hardcoded in the server, and therefore untranslated; that's
559
+ // zulip/zulip#3639.
560
+ const String kNoTopicTopic = '(no topic)' ;
561
+
553
562
/// The name of a Zulip topic.
554
563
// TODO(dart): Can we forbid calling Object members on this extension type?
555
564
// (The lack of "implements Object" ought to do that, but doesn't.)
@@ -604,6 +613,51 @@ extension type const TopicName(String _value) {
604
613
/// using [canonicalize] .
605
614
bool isSameAs (TopicName other) => canonicalize () == other.canonicalize ();
606
615
616
+ /// Process this topic to match how it would appear on a message object from
617
+ /// the server.
618
+ ///
619
+ /// This assumes that the topic is constructed from a string without
620
+ /// leading/trailing whitespace.
621
+ ///
622
+ /// For a client that does not support empty topics, when FL>=334, the server
623
+ /// converts empty topics to `store.realmEmptyTopicDisplayName` ; when FL>=370,
624
+ /// the server converts "(no topic)" to `store.realmEmptyTopicDisplayName`
625
+ /// as well.
626
+ ///
627
+ /// See API docs:
628
+ /// https://zulip.com/api/send-message#parameter-topic
629
+ TopicName processLikeServer ({
630
+ required int zulipFeatureLevel,
631
+ required String ? realmEmptyTopicDisplayName,
632
+ }) {
633
+ assert (_value.trim () == _value);
634
+ // TODO(server-10) simplify this away
635
+ if (zulipFeatureLevel < 334 ) {
636
+ // From the API docs:
637
+ // > Before Zulip 10.0 (feature level 334), empty string was not a valid
638
+ // > topic name for channel messages.
639
+ assert (_value.isNotEmpty);
640
+ return this ;
641
+ }
642
+
643
+ // TODO(server-10) simplify this away
644
+ if (zulipFeatureLevel < 370 && _value == kNoTopicTopic) {
645
+ // From the API docs:
646
+ // > Before Zulip 10.0 (feature level 370), "(no topic)" was not
647
+ // > interpreted as an empty string.
648
+ return TopicName (kNoTopicTopic);
649
+ }
650
+
651
+ // TODO(#1250): This assumes that the 'empty_topic_name' client capability
652
+ // is not declared. When we set 'empty_topic_name' to true,
653
+ // make this return an empty topic if the value matches "(no topic)"
654
+ // or realmEmptyTopicDisplayName.
655
+ if (_value == kNoTopicTopic || _value.isEmpty) {
656
+ return TopicName (realmEmptyTopicDisplayName! );
657
+ }
658
+ return TopicName (_value);
659
+ }
660
+
607
661
TopicName .fromJson (this ._value);
608
662
609
663
String toJson () => apiName;
0 commit comments