@@ -394,96 +394,6 @@ class ComposeContentController extends ComposeController<ContentValidationError>
394394 }
395395}
396396
397- class _ContentInput extends StatefulWidget {
398- const _ContentInput ({
399- required this .narrow,
400- required this .controller,
401- required this .hintText,
402- });
403-
404- final Narrow narrow;
405- final ComposeBoxController controller;
406- final String hintText;
407-
408- @override
409- State <StatefulWidget > createState () => _ContentInputState ();
410- }
411-
412- class _ContentInputState <T extends _ContentInput > extends State <T > {
413- static double maxHeight (BuildContext context) {
414- final clampingTextScaler = MediaQuery .textScalerOf (context)
415- .clamp (maxScaleFactor: 1.5 );
416- final scaledLineHeight = clampingTextScaler.scale (_fontSize) * _lineHeightRatio;
417-
418- // Reserve space to fully show the first 7th lines and just partially
419- // clip the 8th line, where the height matches the spec at
420- // https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=3960-5147&node-type=text&m=dev
421- // > Maximum size of the compose box is suggested to be 178px. Which
422- // > has 7 fully visible lines of text
423- //
424- // The partial line hints that the content input is scrollable.
425- //
426- // Using the ambient TextScale means this works for different values of the
427- // system text-size setting. We clamp to a max scale factor to limit
428- // how tall the content input can get; that's to save room for the message
429- // list. The user can still scroll the input to see everything.
430- return _verticalPadding + 7.727 * scaledLineHeight;
431- }
432-
433- static const _verticalPadding = 8.0 ;
434- static const _fontSize = 17.0 ;
435- static const _lineHeight = 22.0 ;
436- static const _lineHeightRatio = _lineHeight / _fontSize;
437-
438- @override
439- Widget build (BuildContext context) {
440- final designVariables = DesignVariables .of (context);
441-
442- return ComposeAutocomplete (
443- narrow: widget.narrow,
444- controller: widget.controller.content,
445- focusNode: widget.controller.contentFocusNode,
446- fieldViewBuilder: (context) => ConstrainedBox (
447- constraints: BoxConstraints (maxHeight: maxHeight (context)),
448- // This [ClipRect] replaces the [TextField] clipping we disable below.
449- child: ClipRect (
450- child: InsetShadowBox (
451- top: _verticalPadding, bottom: _verticalPadding,
452- color: designVariables.composeBoxBg,
453- child: TextField (
454- controller: widget.controller.content,
455- focusNode: widget.controller.contentFocusNode,
456- // Let the content show through the `contentPadding` so that
457- // our [InsetShadowBox] can fade it smoothly there.
458- clipBehavior: Clip .none,
459- style: TextStyle (
460- fontSize: _fontSize,
461- height: _lineHeightRatio,
462- color: designVariables.textInput),
463- // From the spec at
464- // https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=3960-5147&node-type=text&m=dev
465- // > Compose box has the height to fit 2 lines. This is [done] to
466- // > have a bigger hit area for the user to start the input. […]
467- minLines: 2 ,
468- maxLines: null ,
469- textCapitalization: TextCapitalization .sentences,
470- decoration: InputDecoration (
471- // This padding ensures that the user can always scroll long
472- // content entirely out of the top or bottom shadow if desired.
473- // With this and the `minLines: 2` above, an empty content input
474- // gets 60px vertical distance (with no text-size scaling)
475- // between the top of the top shadow and the bottom of the
476- // bottom shadow. That's a bit more than the 54px given in the
477- // Figma, and we can revisit if needed, but it's tricky to get
478- // that 54px distance while also making the scrolling work like
479- // this and offering two lines of touchable area.
480- contentPadding: const EdgeInsets .symmetric (vertical: _verticalPadding),
481- hintText: widget.hintText,
482- hintStyle: TextStyle (
483- color: designVariables.textInput.withFadedAlpha (0.5 ))))))));
484- }
485- }
486-
487397class _TypingNotifier extends StatefulWidget {
488398 const _TypingNotifier ({
489399 required this .destination,
@@ -576,6 +486,96 @@ class _TypingNotifierState extends State<_TypingNotifier> with WidgetsBindingObs
576486 Widget build (BuildContext context) => widget.child;
577487}
578488
489+ class _ContentInput extends StatefulWidget {
490+ const _ContentInput ({
491+ required this .narrow,
492+ required this .controller,
493+ required this .hintText,
494+ });
495+
496+ final Narrow narrow;
497+ final ComposeBoxController controller;
498+ final String hintText;
499+
500+ @override
501+ State <StatefulWidget > createState () => _ContentInputState ();
502+ }
503+
504+ class _ContentInputState <T extends _ContentInput > extends State <T > {
505+ static double maxHeight (BuildContext context) {
506+ final clampingTextScaler = MediaQuery .textScalerOf (context)
507+ .clamp (maxScaleFactor: 1.5 );
508+ final scaledLineHeight = clampingTextScaler.scale (_fontSize) * _lineHeightRatio;
509+
510+ // Reserve space to fully show the first 7th lines and just partially
511+ // clip the 8th line, where the height matches the spec at
512+ // https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=3960-5147&node-type=text&m=dev
513+ // > Maximum size of the compose box is suggested to be 178px. Which
514+ // > has 7 fully visible lines of text
515+ //
516+ // The partial line hints that the content input is scrollable.
517+ //
518+ // Using the ambient TextScale means this works for different values of the
519+ // system text-size setting. We clamp to a max scale factor to limit
520+ // how tall the content input can get; that's to save room for the message
521+ // list. The user can still scroll the input to see everything.
522+ return _verticalPadding + 7.727 * scaledLineHeight;
523+ }
524+
525+ static const _verticalPadding = 8.0 ;
526+ static const _fontSize = 17.0 ;
527+ static const _lineHeight = 22.0 ;
528+ static const _lineHeightRatio = _lineHeight / _fontSize;
529+
530+ @override
531+ Widget build (BuildContext context) {
532+ final designVariables = DesignVariables .of (context);
533+
534+ return ComposeAutocomplete (
535+ narrow: widget.narrow,
536+ controller: widget.controller.content,
537+ focusNode: widget.controller.contentFocusNode,
538+ fieldViewBuilder: (context) => ConstrainedBox (
539+ constraints: BoxConstraints (maxHeight: maxHeight (context)),
540+ // This [ClipRect] replaces the [TextField] clipping we disable below.
541+ child: ClipRect (
542+ child: InsetShadowBox (
543+ top: _verticalPadding, bottom: _verticalPadding,
544+ color: designVariables.composeBoxBg,
545+ child: TextField (
546+ controller: widget.controller.content,
547+ focusNode: widget.controller.contentFocusNode,
548+ // Let the content show through the `contentPadding` so that
549+ // our [InsetShadowBox] can fade it smoothly there.
550+ clipBehavior: Clip .none,
551+ style: TextStyle (
552+ fontSize: _fontSize,
553+ height: _lineHeightRatio,
554+ color: designVariables.textInput),
555+ // From the spec at
556+ // https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=3960-5147&node-type=text&m=dev
557+ // > Compose box has the height to fit 2 lines. This is [done] to
558+ // > have a bigger hit area for the user to start the input. […]
559+ minLines: 2 ,
560+ maxLines: null ,
561+ textCapitalization: TextCapitalization .sentences,
562+ decoration: InputDecoration (
563+ // This padding ensures that the user can always scroll long
564+ // content entirely out of the top or bottom shadow if desired.
565+ // With this and the `minLines: 2` above, an empty content input
566+ // gets 60px vertical distance (with no text-size scaling)
567+ // between the top of the top shadow and the bottom of the
568+ // bottom shadow. That's a bit more than the 54px given in the
569+ // Figma, and we can revisit if needed, but it's tricky to get
570+ // that 54px distance while also making the scrolling work like
571+ // this and offering two lines of touchable area.
572+ contentPadding: const EdgeInsets .symmetric (vertical: _verticalPadding),
573+ hintText: widget.hintText,
574+ hintStyle: TextStyle (
575+ color: designVariables.textInput.withFadedAlpha (0.5 ))))))));
576+ }
577+ }
578+
579579/// The content input for _StreamComposeBox.
580580class _StreamContentInput extends StatefulWidget {
581581 const _StreamContentInput ({required this .narrow, required this .controller});
0 commit comments