diff --git a/lib/widgets/compose_box.dart b/lib/widgets/compose_box.dart index 1233964afb..3058425bf1 100644 --- a/lib/widgets/compose_box.dart +++ b/lib/widgets/compose_box.dart @@ -22,6 +22,59 @@ import 'store.dart'; import 'text.dart'; import 'theme.dart'; +/// Compose-box styles that differ between light and dark theme. +/// +/// These styles will animate on theme changes (with help from [lerp]). +class ComposeBoxTheme extends ThemeExtension { + static final light = ComposeBoxTheme._( + boxShadow: null, + ); + + static final dark = ComposeBoxTheme._( + boxShadow: [BoxShadow( + color: DesignVariables.dark.bgTopBar, + offset: const Offset(0, -4), + blurRadius: 16, + spreadRadius: 0, + )], + ); + + ComposeBoxTheme._({ + required this.boxShadow, + }); + + /// The [ComposeBoxTheme] from the context's active theme. + /// + /// The [ThemeData] must include [ComposeBoxTheme] in [ThemeData.extensions]. + static ComposeBoxTheme of(BuildContext context) { + final theme = Theme.of(context); + final extension = theme.extension(); + assert(extension != null); + return extension!; + } + + final List? boxShadow; + + @override + ComposeBoxTheme copyWith({ + List? boxShadow, + }) { + return ComposeBoxTheme._( + boxShadow: boxShadow ?? this.boxShadow, + ); + } + + @override + ComposeBoxTheme lerp(ComposeBoxTheme other, double t) { + if (identical(this, other)) { + return this; + } + return ComposeBoxTheme._( + boxShadow: BoxShadow.lerpList(boxShadow, other.boxShadow, t)!, + ); + } +} + const double _composeButtonSize = 44; /// A [TextEditingController] for use in the compose box. @@ -1090,7 +1143,9 @@ class _ComposeBoxContainer extends StatelessWidget { // the message list itself; if so, remember to update ComposeBox's dartdoc. return Container(width: double.infinity, decoration: BoxDecoration( - border: Border(top: BorderSide(color: designVariables.borderBar))), + border: Border(top: BorderSide(color: designVariables.borderBar)), + boxShadow: ComposeBoxTheme.of(context).boxShadow, + ), // TODO(#720) try a Stack for the overlaid linear progress indicator child: Material( color: designVariables.composeBoxBg, diff --git a/lib/widgets/theme.dart b/lib/widgets/theme.dart index 5358f73c42..ec8ad8aecc 100644 --- a/lib/widgets/theme.dart +++ b/lib/widgets/theme.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import '../api/model/model.dart'; +import 'compose_box.dart'; import 'content.dart'; import 'emoji_reaction.dart'; import 'message_list.dart'; @@ -32,6 +33,7 @@ ThemeData zulipThemeData(BuildContext context) { designVariables, EmojiReactionTheme.light, MessageListTheme.light, + ComposeBoxTheme.light, ]; } case Brightness.dark: { @@ -41,6 +43,7 @@ ThemeData zulipThemeData(BuildContext context) { designVariables, EmojiReactionTheme.dark, MessageListTheme.dark, + ComposeBoxTheme.dark, ]; } } @@ -175,7 +178,7 @@ class DesignVariables extends ThemeExtension { bgMenuButtonActive: Colors.black.withValues(alpha: 0.2), bgMenuButtonSelected: Colors.black.withValues(alpha: 0.25), bgTopBar: const Color(0xff242424), - borderBar: Colors.black.withValues(alpha: 0.5), + borderBar: const Color(0xffffffff).withValues(alpha: 0.1), borderMenuButtonSelected: Colors.white.withValues(alpha: 0.1), btnLabelAttLowIntDanger: const Color(0xffff8b7c), btnLabelAttMediumIntDanger: const Color(0xffff8b7c), diff --git a/test/widgets/compose_box_test.dart b/test/widgets/compose_box_test.dart index a5032f5705..f1eb9bb3ba 100644 --- a/test/widgets/compose_box_test.dart +++ b/test/widgets/compose_box_test.dart @@ -111,6 +111,15 @@ void main() { await tester.pump(Duration.zero); } + group('ComposeBoxTheme', () { + test('lerp light to dark, no crash', () { + final a = ComposeBoxTheme.light; + final b = ComposeBoxTheme.dark; + + check(() => a.lerp(b, 0.5)).returnsNormally(); + }); + }); + group('ComposeContentController', () { group('insertPadded', () { // Like `parseMarkedText` in test/model/autocomplete_test.dart,