Skip to content

Commit cd369ff

Browse files
committed
compose [nfc]: Factor _Banner as a concrete widget class with params
Instead of as a base class with subclasses _ErrorBanner and _EditMessageBanner.
1 parent a1a37c7 commit cd369ff

File tree

1 file changed

+45
-57
lines changed

1 file changed

+45
-57
lines changed

lib/widgets/compose_box.dart

Lines changed: 45 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,38 +1724,45 @@ class EditMessageComposeBoxController extends ComposeBoxController {
17241724
/// A banner to display over or instead of interactive compose-box content.
17251725
///
17261726
/// Must have a [PageRoot] ancestor.
1727-
abstract class _Banner extends StatelessWidget {
1728-
const _Banner();
1729-
1730-
_BannerIntent get intent;
1727+
class _Banner extends StatelessWidget {
1728+
const _Banner({
1729+
required this.intent,
1730+
required this.label,
1731+
this.trailing,
1732+
this.padEnd = true, // ignore: unused_element_parameter
1733+
});
17311734

1732-
String getLabel(ZulipLocalizations zulipLocalizations);
1735+
final _BannerIntent intent;
1736+
final String label;
17331737

1734-
/// A trailing element, with vertical but not horizontal outer padding
1738+
/// An optional trailing element.
1739+
///
1740+
/// It should include vertical but not horizontal outer padding
17351741
/// for spacing/positioning.
17361742
///
17371743
/// An interactive element's touchable area should have height at least 44px,
17381744
/// with some of that as "slop" vertical outer padding above and below
17391745
/// what gets painted:
17401746
/// https://github.com/zulip/zulip-flutter/pull/1432#discussion_r2023907300
17411747
///
1742-
/// To control the element's distance from the end edge, override [padEnd].
1743-
///
1744-
/// The passed [BuildContext] will be the result of [PageRoot.contextOf],
1745-
/// so it's expected to remain mounted until the whole page disappears,
1746-
/// which may be long after the banner disappears.
1747-
Widget? buildTrailing(BuildContext pageContext);
1748+
/// To control the element's distance from the end edge, use [padEnd].
1749+
// An "x" button could go here.
1750+
// 24px square with 8px touchable padding in all directions?
1751+
// and `padEnd: false`; see Figma:
1752+
// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=4031-17029&m=dev
1753+
final Widget? trailing;
17481754

17491755
/// Whether to apply `end: 8` in [SafeArea.minimum].
17501756
///
1751-
/// Subclasses can use `false` when the [buildTrailing] element
1757+
/// Pass `false` when the [trailing] element
17521758
/// is meant to abut the edge of the screen
17531759
/// in the common case that there are no horizontal device insets.
1754-
bool get padEnd => true;
1760+
///
1761+
/// Defaults to `true`.
1762+
final bool padEnd;
17551763

17561764
@override
17571765
Widget build(BuildContext context) {
1758-
final zulipLocalizations = ZulipLocalizations.of(context);
17591766
final designVariables = DesignVariables.of(context);
17601767

17611768
final (labelColor, backgroundColor) = switch (intent) {
@@ -1771,7 +1778,6 @@ abstract class _Banner extends StatelessWidget {
17711778
color: labelColor,
17721779
).merge(weightVariableTextStyle(context, wght: 600));
17731780

1774-
final trailing = buildTrailing(PageRoot.contextOf(context));
17751781
return DecoratedBox(
17761782
decoration: BoxDecoration(color: backgroundColor),
17771783
child: SafeArea(
@@ -1788,10 +1794,10 @@ abstract class _Banner extends StatelessWidget {
17881794
child: Text(
17891795
style: labelTextStyle,
17901796
textScaler: MediaQuery.textScalerOf(context).clamp(maxScaleFactor: 1.5),
1791-
getLabel(zulipLocalizations)))),
1797+
label))),
17921798
if (trailing != null) ...[
17931799
const SizedBox(width: 8),
1794-
trailing,
1800+
trailing!,
17951801
],
17961802
]))));
17971803
}
@@ -1802,41 +1808,11 @@ enum _BannerIntent {
18021808
danger,
18031809
}
18041810

1805-
class _ErrorBanner extends _Banner {
1806-
const _ErrorBanner({
1807-
required String Function(ZulipLocalizations) getLabel,
1808-
}) : _getLabel = getLabel;
1809-
1810-
@override
1811-
String getLabel(ZulipLocalizations zulipLocalizations) =>
1812-
_getLabel(zulipLocalizations);
1813-
final String Function(ZulipLocalizations) _getLabel;
1814-
1815-
@override
1816-
_BannerIntent get intent => _BannerIntent.danger;
1817-
1818-
@override
1819-
Widget? buildTrailing(pageContext) {
1820-
// An "x" button can go here.
1821-
// 24px square with 8px touchable padding in all directions?
1822-
// and `bool get padEnd => false`; see Figma:
1823-
// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=4031-17029&m=dev
1824-
return null;
1825-
}
1826-
}
1827-
1828-
class _EditMessageBanner extends _Banner {
1829-
const _EditMessageBanner({required this.composeBoxState});
1811+
class _EditMessageBannerTrailing extends StatelessWidget {
1812+
const _EditMessageBannerTrailing({required this.composeBoxState});
18301813

18311814
final ComposeBoxState composeBoxState;
18321815

1833-
@override
1834-
String getLabel(ZulipLocalizations zulipLocalizations) =>
1835-
zulipLocalizations.composeBoxBannerLabelEditMessage;
1836-
1837-
@override
1838-
_BannerIntent get intent => _BannerIntent.info;
1839-
18401816
void _handleTapSave (BuildContext pageContext) async {
18411817
final store = PerAccountStoreWidget.of(pageContext);
18421818
final controller = composeBoxState.controller;
@@ -1884,7 +1860,11 @@ class _EditMessageBanner extends _Banner {
18841860
}
18851861

18861862
@override
1887-
Widget buildTrailing(pageContext) {
1863+
Widget build(BuildContext context) {
1864+
// (A BuildContext that's expected to remain mounted until the whole page
1865+
// disappears, which may be long after the banner disappears.)
1866+
final pageContext = PageRoot.contextOf(context);
1867+
18881868
final zulipLocalizations = ZulipLocalizations.of(pageContext);
18891869
return Row(mainAxisSize: MainAxisSize.min, spacing: 8, children: [
18901870
ZulipWebUiKitButton(label: zulipLocalizations.composeBoxBannerButtonCancel,
@@ -2148,25 +2128,28 @@ class _ComposeBoxState extends State<ComposeBox> with PerAccountStoreAwareStateM
21482128
super.dispose();
21492129
}
21502130

2151-
/// An [_ErrorBanner] that replaces the compose box's text inputs.
2131+
/// A [_Banner] that replaces the compose box's text inputs.
21522132
Widget? _errorBannerComposingNotAllowed(BuildContext context) {
21532133
final store = PerAccountStoreWidget.of(context);
2134+
final zulipLocalizations = ZulipLocalizations.of(context);
21542135
switch (widget.narrow) {
21552136
case ChannelNarrow(:final streamId):
21562137
case TopicNarrow(:final streamId):
21572138
final channel = store.streams[streamId];
21582139
if (channel == null || !store.selfCanSendMessage(inChannel: channel,
21592140
byDate: DateTime.now())) {
2160-
return _ErrorBanner(getLabel: (zulipLocalizations) =>
2161-
zulipLocalizations.errorBannerCannotPostInChannelLabel);
2141+
return _Banner(
2142+
intent: _BannerIntent.danger,
2143+
label: zulipLocalizations.errorBannerCannotPostInChannelLabel);
21622144
}
21632145

21642146
case DmNarrow(:final otherRecipientIds):
21652147
final hasDeactivatedUser = otherRecipientIds.any((id) =>
21662148
!(store.getUser(id)?.isActive ?? true));
21672149
if (hasDeactivatedUser) {
2168-
return _ErrorBanner(getLabel: (zulipLocalizations) =>
2169-
zulipLocalizations.errorBannerDeactivatedDmLabel);
2150+
return _Banner(
2151+
intent: _BannerIntent.danger,
2152+
label: zulipLocalizations.errorBannerDeactivatedDmLabel);
21702153
}
21712154

21722155
case CombinedFeedNarrow():
@@ -2180,6 +2163,8 @@ class _ComposeBoxState extends State<ComposeBox> with PerAccountStoreAwareStateM
21802163

21812164
@override
21822165
Widget build(BuildContext context) {
2166+
final zulipLocalizations = ZulipLocalizations.of(context);
2167+
21832168
final errorBanner = _errorBannerComposingNotAllowed(context);
21842169
if (errorBanner != null) {
21852170
return ComposeBoxInheritedWidget.fromComposeBoxState(this,
@@ -2202,7 +2187,10 @@ class _ComposeBoxState extends State<ComposeBox> with PerAccountStoreAwareStateM
22022187
}
22032188
case EditMessageComposeBoxController(): {
22042189
body = _EditMessageComposeBoxBody(controller: controller, narrow: narrow);
2205-
banner = _EditMessageBanner(composeBoxState: this);
2190+
banner = _Banner(
2191+
intent: _BannerIntent.info,
2192+
label: zulipLocalizations.composeBoxBannerLabelEditMessage,
2193+
trailing: _EditMessageBannerTrailing(composeBoxState: this));
22062194
}
22072195
}
22082196

0 commit comments

Comments
 (0)