@@ -327,6 +327,48 @@ class _StreamContentInputState extends State<_StreamContentInput> {
327
327
}
328
328
}
329
329
330
+ class _FixedDestinationContentInput extends StatelessWidget {
331
+ const _FixedDestinationContentInput ({
332
+ required this .narrow,
333
+ required this .controller,
334
+ required this .focusNode,
335
+ });
336
+
337
+ final SendableNarrow narrow;
338
+ final ComposeContentController controller;
339
+ final FocusNode focusNode;
340
+
341
+ String _hintText (BuildContext context) {
342
+ switch (narrow) {
343
+ case TopicNarrow (: final streamId, : final topic):
344
+ final store = PerAccountStoreWidget .of (context);
345
+ final streamName = store.streams[streamId]? .name ?? '(unknown stream)' ;
346
+ return "Message #$streamName > $topic " ;
347
+
348
+ case DmNarrow (otherRecipientIds: []): // The self-1:1 thread.
349
+ return "Jot down something" ;
350
+
351
+ case DmNarrow (otherRecipientIds: [final otherUserId]):
352
+ final store = PerAccountStoreWidget .of (context);
353
+ final fullName = store.users[otherUserId]? .fullName;
354
+ if (fullName == null ) return 'Type a message' ;
355
+ return 'Message @$fullName ' ;
356
+
357
+ case DmNarrow (): // A group DM thread.
358
+ return 'Message group' ;
359
+ }
360
+ }
361
+
362
+ @override
363
+ Widget build (BuildContext context) {
364
+ return _ContentInput (
365
+ narrow: narrow,
366
+ controller: controller,
367
+ focusNode: focusNode,
368
+ hintText: _hintText (context));
369
+ }
370
+ }
371
+
330
372
/// Data on a file to be uploaded, from any source.
331
373
///
332
374
/// A convenience class to represent data from the generic file picker,
@@ -785,6 +827,45 @@ class _StreamComposeBoxState extends State<_StreamComposeBox> {
785
827
}
786
828
}
787
829
830
+ class _FixedDestinationComposeBox extends StatefulWidget {
831
+ const _FixedDestinationComposeBox ({required this .narrow});
832
+
833
+ final SendableNarrow narrow;
834
+
835
+ @override
836
+ State <_FixedDestinationComposeBox > createState () => _FixedDestinationComposeBoxState ();
837
+ }
838
+
839
+ class _FixedDestinationComposeBoxState extends State <_FixedDestinationComposeBox > {
840
+ final _contentController = ComposeContentController ();
841
+ final _contentFocusNode = FocusNode ();
842
+
843
+ @override
844
+ void dispose () {
845
+ _contentController.dispose ();
846
+ _contentFocusNode.dispose ();
847
+ super .dispose ();
848
+ }
849
+
850
+ @override
851
+ Widget build (BuildContext context) {
852
+ return _ComposeBoxLayout (
853
+ contentController: _contentController,
854
+ contentFocusNode: _contentFocusNode,
855
+ topicInput: null ,
856
+ contentInput: _FixedDestinationContentInput (
857
+ narrow: widget.narrow,
858
+ controller: _contentController,
859
+ focusNode: _contentFocusNode,
860
+ ),
861
+ sendButton: _SendButton (
862
+ topicController: null ,
863
+ contentController: _contentController,
864
+ getDestination: () => widget.narrow.destination,
865
+ ));
866
+ }
867
+ }
868
+
788
869
class ComposeBox extends StatelessWidget {
789
870
const ComposeBox ({super .key, required this .narrow});
790
871
@@ -796,9 +877,9 @@ class ComposeBox extends StatelessWidget {
796
877
if (narrow is StreamNarrow ) {
797
878
return _StreamComposeBox (narrow: narrow);
798
879
} else if (narrow is TopicNarrow ) {
799
- return const SizedBox . shrink (); // TODO(#144): add a single-topic compose box
880
+ return _FixedDestinationComposeBox (narrow : narrow);
800
881
} else if (narrow is DmNarrow ) {
801
- return const SizedBox . shrink (); // TODO(#144): add a DM compose box
882
+ return _FixedDestinationComposeBox (narrow : narrow);
802
883
} else if (narrow is AllMessagesNarrow ) {
803
884
return const SizedBox .shrink ();
804
885
} else {
0 commit comments