@@ -1724,38 +1724,45 @@ class EditMessageComposeBoxController extends ComposeBoxController {
1724
1724
/// A banner to display over or instead of interactive compose-box content.
1725
1725
///
1726
1726
/// 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
+ });
1731
1734
1732
- String getLabel (ZulipLocalizations zulipLocalizations);
1735
+ final _BannerIntent intent;
1736
+ final String label;
1733
1737
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
1735
1741
/// for spacing/positioning.
1736
1742
///
1737
1743
/// An interactive element's touchable area should have height at least 44px,
1738
1744
/// with some of that as "slop" vertical outer padding above and below
1739
1745
/// what gets painted:
1740
1746
/// https://github.com/zulip/zulip-flutter/pull/1432#discussion_r2023907300
1741
1747
///
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 ;
1748
1754
1749
1755
/// Whether to apply `end: 8` in [SafeArea.minimum] .
1750
1756
///
1751
- /// Subclasses can use `false` when the [buildTrailing ] element
1757
+ /// Pass `false` when the [trailing ] element
1752
1758
/// is meant to abut the edge of the screen
1753
1759
/// 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;
1755
1763
1756
1764
@override
1757
1765
Widget build (BuildContext context) {
1758
- final zulipLocalizations = ZulipLocalizations .of (context);
1759
1766
final designVariables = DesignVariables .of (context);
1760
1767
1761
1768
final (labelColor, backgroundColor) = switch (intent) {
@@ -1771,7 +1778,6 @@ abstract class _Banner extends StatelessWidget {
1771
1778
color: labelColor,
1772
1779
).merge (weightVariableTextStyle (context, wght: 600 ));
1773
1780
1774
- final trailing = buildTrailing (PageRoot .contextOf (context));
1775
1781
return DecoratedBox (
1776
1782
decoration: BoxDecoration (color: backgroundColor),
1777
1783
child: SafeArea (
@@ -1788,10 +1794,10 @@ abstract class _Banner extends StatelessWidget {
1788
1794
child: Text (
1789
1795
style: labelTextStyle,
1790
1796
textScaler: MediaQuery .textScalerOf (context).clamp (maxScaleFactor: 1.5 ),
1791
- getLabel (zulipLocalizations) ))),
1797
+ label ))),
1792
1798
if (trailing != null ) ...[
1793
1799
const SizedBox (width: 8 ),
1794
- trailing,
1800
+ trailing! ,
1795
1801
],
1796
1802
]))));
1797
1803
}
@@ -1802,41 +1808,11 @@ enum _BannerIntent {
1802
1808
danger,
1803
1809
}
1804
1810
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});
1830
1813
1831
1814
final ComposeBoxState composeBoxState;
1832
1815
1833
- @override
1834
- String getLabel (ZulipLocalizations zulipLocalizations) =>
1835
- zulipLocalizations.composeBoxBannerLabelEditMessage;
1836
-
1837
- @override
1838
- _BannerIntent get intent => _BannerIntent .info;
1839
-
1840
1816
void _handleTapSave (BuildContext pageContext) async {
1841
1817
final store = PerAccountStoreWidget .of (pageContext);
1842
1818
final controller = composeBoxState.controller;
@@ -1884,7 +1860,11 @@ class _EditMessageBanner extends _Banner {
1884
1860
}
1885
1861
1886
1862
@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
+
1888
1868
final zulipLocalizations = ZulipLocalizations .of (pageContext);
1889
1869
return Row (mainAxisSize: MainAxisSize .min, spacing: 8 , children: [
1890
1870
ZulipWebUiKitButton (label: zulipLocalizations.composeBoxBannerButtonCancel,
@@ -2148,25 +2128,28 @@ class _ComposeBoxState extends State<ComposeBox> with PerAccountStoreAwareStateM
2148
2128
super .dispose ();
2149
2129
}
2150
2130
2151
- /// An [_ErrorBanner ] that replaces the compose box's text inputs.
2131
+ /// A [_Banner ] that replaces the compose box's text inputs.
2152
2132
Widget ? _errorBannerComposingNotAllowed (BuildContext context) {
2153
2133
final store = PerAccountStoreWidget .of (context);
2134
+ final zulipLocalizations = ZulipLocalizations .of (context);
2154
2135
switch (widget.narrow) {
2155
2136
case ChannelNarrow (: final streamId):
2156
2137
case TopicNarrow (: final streamId):
2157
2138
final channel = store.streams[streamId];
2158
2139
if (channel == null || ! store.selfCanSendMessage (inChannel: channel,
2159
2140
byDate: DateTime .now ())) {
2160
- return _ErrorBanner (getLabel: (zulipLocalizations) =>
2161
- zulipLocalizations.errorBannerCannotPostInChannelLabel);
2141
+ return _Banner (
2142
+ intent: _BannerIntent .danger,
2143
+ label: zulipLocalizations.errorBannerCannotPostInChannelLabel);
2162
2144
}
2163
2145
2164
2146
case DmNarrow (: final otherRecipientIds):
2165
2147
final hasDeactivatedUser = otherRecipientIds.any ((id) =>
2166
2148
! (store.getUser (id)? .isActive ?? true ));
2167
2149
if (hasDeactivatedUser) {
2168
- return _ErrorBanner (getLabel: (zulipLocalizations) =>
2169
- zulipLocalizations.errorBannerDeactivatedDmLabel);
2150
+ return _Banner (
2151
+ intent: _BannerIntent .danger,
2152
+ label: zulipLocalizations.errorBannerDeactivatedDmLabel);
2170
2153
}
2171
2154
2172
2155
case CombinedFeedNarrow ():
@@ -2180,6 +2163,8 @@ class _ComposeBoxState extends State<ComposeBox> with PerAccountStoreAwareStateM
2180
2163
2181
2164
@override
2182
2165
Widget build (BuildContext context) {
2166
+ final zulipLocalizations = ZulipLocalizations .of (context);
2167
+
2183
2168
final errorBanner = _errorBannerComposingNotAllowed (context);
2184
2169
if (errorBanner != null ) {
2185
2170
return ComposeBoxInheritedWidget .fromComposeBoxState (this ,
@@ -2202,7 +2187,10 @@ class _ComposeBoxState extends State<ComposeBox> with PerAccountStoreAwareStateM
2202
2187
}
2203
2188
case EditMessageComposeBoxController (): {
2204
2189
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 ));
2206
2194
}
2207
2195
}
2208
2196
0 commit comments