Skip to content

Commit 82bd1a9

Browse files
committed
compose: Show alternative hint text if topic is vacuous and mandatory
Signed-off-by: Zixuan James Li <[email protected]>
1 parent 0c3f0c7 commit 82bd1a9

File tree

2 files changed

+49
-11
lines changed

2 files changed

+49
-11
lines changed

lib/widgets/compose_box.dart

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,23 @@ class ComposeTopicController extends ComposeController<TopicValidationError> {
167167
/// that certain strings are not empty but also indicate the absence of a topic.
168168
bool get isTopicVacuous => textNormalized == kNoTopicTopic;
169169

170+
/// The send destination as a string.
171+
///
172+
/// This returns a string formatted like "#stream name" when topics are
173+
/// mandatory but [textNormalized] is vacuous (see [isTopicVacuous]).
174+
///
175+
/// Otherwise, returns a string formatted like "#stream name > topic name".
176+
// No i18n of the use of "#" and ">" strings; those are part of how
177+
// Zulip expresses channels and topics, not any normal English punctuation,
178+
// so don't make sense to translate. See:
179+
// https://github.com/zulip/zulip-flutter/pull/1148#discussion_r1941990585
180+
String getDestinationString({required String streamName}) {
181+
if (mandatory && isTopicVacuous) {
182+
return '#$streamName';
183+
}
184+
return '#$streamName > $textNormalized';
185+
}
186+
170187
@override
171188
List<TopicValidationError> _computeValidationErrors() {
172189
return [
@@ -585,17 +602,13 @@ class _StreamContentInputState extends State<_StreamContentInput> {
585602
final zulipLocalizations = ZulipLocalizations.of(context);
586603
final streamName = store.streams[widget.narrow.streamId]?.name
587604
?? zulipLocalizations.unknownChannelName;
588-
final topic = TopicName(widget.controller.topic.textNormalized);
589605
return _ContentInput(
590606
narrow: widget.narrow,
591-
destination: TopicNarrow(widget.narrow.streamId, topic),
607+
destination: TopicNarrow(widget.narrow.streamId,
608+
TopicName(widget.controller.topic.textNormalized)),
592609
controller: widget.controller,
593610
hintText: zulipLocalizations.composeBoxChannelContentHint(
594-
// No i18n of this use of "#" and ">" string; those are part of how
595-
// Zulip expresses channels and topics, not any normal English punctuation,
596-
// so don't make sense to translate. See:
597-
// https://github.com/zulip/zulip-flutter/pull/1148#discussion_r1941990585
598-
'#$streamName > ${topic.displayName}'));
611+
widget.controller.topic.getDestinationString(streamName: streamName)));
599612
}
600613
}
601614

test/widgets/compose_box_test.dart

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,11 +326,13 @@ void main() {
326326

327327
Future<void> prepare(WidgetTester tester, {
328328
required Narrow narrow,
329+
bool? mandatoryTopics,
329330
}) async {
330331
await prepareComposeBox(tester,
331332
narrow: narrow,
332333
otherUsers: [eg.otherUser, eg.thirdUser],
333-
streams: [channel]);
334+
streams: [channel],
335+
mandatoryTopics: mandatoryTopics);
334336
}
335337

336338
/// This checks the input's configured hint text without regard to whether
@@ -351,17 +353,40 @@ void main() {
351353
.decoration.isNotNull().hintText.equals(contentHintText);
352354
}
353355

354-
group('to ChannelNarrow', () {
356+
group('to ChannelNarrow, topics not mandatory', () {
355357
testWidgets('with empty topic', (tester) async {
356-
await prepare(tester, narrow: ChannelNarrow(channel.streamId));
358+
await prepare(tester, narrow: ChannelNarrow(channel.streamId),
359+
mandatoryTopics: false);
357360
checkComposeBoxHintTexts(tester,
358361
topicHintText: 'Topic',
359362
contentHintText: 'Message #${channel.name} > (no topic)');
360363
});
361364

362365
testWidgets('with non-empty topic', (tester) async {
363366
final narrow = ChannelNarrow(channel.streamId);
364-
await prepare(tester, narrow: narrow);
367+
await prepare(tester, narrow: narrow,
368+
mandatoryTopics: false);
369+
await enterTopic(tester, narrow: narrow, topic: 'new topic');
370+
await tester.pump();
371+
checkComposeBoxHintTexts(tester,
372+
topicHintText: 'Topic',
373+
contentHintText: 'Message #${channel.name} > new topic');
374+
});
375+
});
376+
377+
group('to ChannelNarrow, mandatory topics', () {
378+
testWidgets('with empty topic', (tester) async {
379+
await prepare(tester, narrow: ChannelNarrow(channel.streamId),
380+
mandatoryTopics: true);
381+
checkComposeBoxHintTexts(tester,
382+
topicHintText: 'Topic',
383+
contentHintText: 'Message #${channel.name}');
384+
});
385+
386+
testWidgets('with non-empty topic', (tester) async {
387+
final narrow = ChannelNarrow(channel.streamId);
388+
await prepare(tester, narrow: narrow,
389+
mandatoryTopics: true);
365390
await enterTopic(tester, narrow: narrow, topic: 'new topic');
366391
await tester.pump();
367392
checkComposeBoxHintTexts(tester,

0 commit comments

Comments
 (0)