Skip to content

Commit bbb781f

Browse files
committed
compose: Change content input hint text statefully
Before, the content input shows the "#stream > topic" hint text as long as it has focus, and set the hint text to "#stream" when it loses focus. Now, the content input still shows "#stream > topic" when it gains focus, except that it will keep showing it even after losing focus, until the user moves focus to the topic input.
1 parent 421290a commit bbb781f

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

lib/widgets/compose_box.dart

+16-5
Original file line numberDiff line numberDiff line change
@@ -595,11 +595,18 @@ class _StreamContentInputState extends State<_StreamContentInput> {
595595
});
596596
}
597597

598+
void _topicEditStatusChanged() {
599+
setState(() {
600+
// The relevant state lives on widget.controller.topicEditStatus itself.
601+
});
602+
}
603+
598604
@override
599605
void initState() {
600606
super.initState();
601607
widget.controller.topic.addListener(_topicChanged);
602608
widget.controller.contentFocusNode.addListener(_contentFocusChanged);
609+
widget.controller.topicEditStatus.addListener(_topicEditStatusChanged);
603610
}
604611

605612
@override
@@ -613,12 +620,17 @@ class _StreamContentInputState extends State<_StreamContentInput> {
613620
oldWidget.controller.contentFocusNode.removeListener(_contentFocusChanged);
614621
widget.controller.contentFocusNode.addListener(_contentFocusChanged);
615622
}
623+
if (widget.controller.topicEditStatus != oldWidget.controller.topicEditStatus) {
624+
oldWidget.controller.topicEditStatus.removeListener(_topicEditStatusChanged);
625+
widget.controller.topicEditStatus.addListener(_topicEditStatusChanged);
626+
}
616627
}
617628

618629
@override
619630
void dispose() {
620631
widget.controller.topic.removeListener(_topicChanged);
621632
widget.controller.contentFocusNode.removeListener(_contentFocusChanged);
633+
widget.controller.topicEditStatus.removeListener(_topicEditStatusChanged);
622634
super.dispose();
623635
}
624636

@@ -629,11 +641,10 @@ class _StreamContentInputState extends State<_StreamContentInput> {
629641
// The chosen topic can't be sent to, so don't show it.
630642
return null;
631643
}
632-
if (!widget.controller.contentFocusNode.hasFocus) {
633-
// Do not fall back to a vacuous topic unless the user explicitly chooses
634-
// to do so (by skipping topic input and moving focus to content input),
635-
// so that the user is not encouraged to use vacuous topic when they
636-
// have not interacted with the inputs at all.
644+
if (widget.controller.topicEditStatus.value != ComposeTopicEditStatus.hasChosen) {
645+
// Do not fall back to a vacuous topic unless the user explicitly
646+
// chooses to do so, so that the user is not encouraged to use vacuous
647+
// topic before they have interacted with the inputs at all.
637648
return null;
638649
}
639650
}

test/widgets/compose_box_test.dart

+17
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,23 @@ void main() {
466466
contentHintText: 'Message #${channel.name}');
467467
});
468468

469+
testWidgets('with empty topic, content input has focus, then loses it', (tester) async {
470+
await prepare(tester, narrow: narrow, mandatoryTopics: false);
471+
await enterContent(tester, '');
472+
await tester.pump();
473+
checkComposeBoxHintTexts(tester,
474+
topicHintText: eg.defaultRealmEmptyTopicDisplayName,
475+
contentHintText: 'Message #${channel.name} > '
476+
'${eg.defaultRealmEmptyTopicDisplayName}');
477+
478+
FocusManager.instance.primaryFocus!.unfocus();
479+
await tester.pump();
480+
checkComposeBoxHintTexts(tester,
481+
topicHintText: eg.defaultRealmEmptyTopicDisplayName,
482+
contentHintText: 'Message #${channel.name} > '
483+
'${eg.defaultRealmEmptyTopicDisplayName}');
484+
});
485+
469486
testWidgets('with non-empty topic', (tester) async {
470487
await prepare(tester, narrow: narrow, mandatoryTopics: false);
471488
await enterTopic(tester, narrow: narrow, topic: 'new topic');

0 commit comments

Comments
 (0)