@@ -1004,6 +1004,7 @@ class _SendButtonState extends State<_SendButton> {
1004
1004
.sendMessage (destination: widget.getDestination (), content: content)
1005
1005
.timeout (kSendMessageTimeout);
1006
1006
widget.controller.content.clear ();
1007
+ widget.controller._sendMessageError.value = null ;
1007
1008
} catch (e) {
1008
1009
if (! mounted) return ;
1009
1010
final zulipLocalizations = ZulipLocalizations .of (context);
@@ -1014,9 +1015,7 @@ class _SendButtonState extends State<_SendButton> {
1014
1015
case TimeoutException (): message = zulipLocalizations.errorSendMessageTimeout;
1015
1016
default : rethrow ;
1016
1017
}
1017
- showErrorDialog (context: context,
1018
- title: zulipLocalizations.errorMessageNotSent,
1019
- message: message);
1018
+ widget.controller._sendMessageError.value = message;
1020
1019
return ;
1021
1020
} finally {
1022
1021
widget.controller._enabled.value = true ;
@@ -1244,11 +1243,15 @@ sealed class ComposeBoxController {
1244
1243
bool get enabled => _enabled.value;
1245
1244
final ValueNotifier <bool > _enabled = ValueNotifier <bool >(true );
1246
1245
1246
+ String ? get sendMessageError => _sendMessageError.value;
1247
+ final ValueNotifier <String ?> _sendMessageError = ValueNotifier <String ?>(null );
1248
+
1247
1249
@mustCallSuper
1248
1250
void dispose () {
1249
1251
content.dispose ();
1250
1252
contentFocusNode.dispose ();
1251
1253
_enabled.dispose ();
1254
+ _sendMessageError.dispose ();
1252
1255
}
1253
1256
}
1254
1257
@@ -1267,13 +1270,15 @@ class StreamComposeBoxController extends ComposeBoxController {
1267
1270
class FixedDestinationComposeBoxController extends ComposeBoxController {}
1268
1271
1269
1272
class _ErrorBanner extends StatelessWidget {
1270
- const _ErrorBanner ({required this .label});
1273
+ const _ErrorBanner ({required this .label, this .onDismiss });
1271
1274
1272
1275
final String label;
1276
+ final void Function ()? onDismiss;
1273
1277
1274
1278
@override
1275
1279
Widget build (BuildContext context) {
1276
1280
final designVariables = DesignVariables .of (context);
1281
+ final iconButtonTheme = IconButtonTheme .of (context);
1277
1282
final labelTextStyle = TextStyle (
1278
1283
fontSize: 17 ,
1279
1284
height: 22 / 17 ,
@@ -1295,8 +1300,14 @@ class _ErrorBanner extends StatelessWidget {
1295
1300
child: Text (style: labelTextStyle,
1296
1301
label))),
1297
1302
const SizedBox (width: 8 ),
1298
- // TODO(#720) "x" button goes here.
1299
- // 24px square with 8px touchable padding in all directions?
1303
+ if (onDismiss != null )
1304
+ IconButton (
1305
+ icon: Icon (
1306
+ ZulipIcons .remove, color: designVariables.btnLabelAttLowIntDanger),
1307
+ style: iconButtonTheme.style! .copyWith (
1308
+ shape: const WidgetStatePropertyAll (ContinuousRectangleBorder (
1309
+ borderRadius: BorderRadius .all (Radius .circular (4 ))))),
1310
+ onPressed: onDismiss),
1300
1311
])));
1301
1312
}
1302
1313
}
@@ -1383,6 +1394,21 @@ class _ComposeBoxState extends State<ComposeBox> implements ComposeBoxState {
1383
1394
return null ;
1384
1395
}
1385
1396
1397
+ Widget _sendMessageErrorErrorBanner (BuildContext context) {
1398
+ final designVariables = DesignVariables .of (context);
1399
+ return ValueListenableBuilder (
1400
+ valueListenable: controller._sendMessageError,
1401
+ builder: (context, sendMessageError, child) {
1402
+ if (sendMessageError == null ) return const SizedBox .shrink ();
1403
+ return _ErrorBanner (
1404
+ label: sendMessageError,
1405
+ onDismiss: () => controller._sendMessageError.value = null );
1406
+ },
1407
+ child: IconButton (icon: Icon (ZulipIcons .remove,
1408
+ color: designVariables.btnLabelAttLowIntDanger),
1409
+ onPressed: () => controller._sendMessageError.value = null ));
1410
+ }
1411
+
1386
1412
@override
1387
1413
Widget build (BuildContext context) {
1388
1414
final Widget ? body;
@@ -1404,11 +1430,7 @@ class _ComposeBoxState extends State<ComposeBox> implements ComposeBoxState {
1404
1430
}
1405
1431
}
1406
1432
1407
- // TODO(#720) dismissable message-send error, maybe something like:
1408
- // if (controller.sendMessageError.value != null) {
1409
- // errorBanner = _ErrorBanner(label:
1410
- // ZulipLocalizations.of(context).errorSendMessageTimeout);
1411
- // }
1412
- return _ComposeBoxContainer (body: body, errorBanner: null );
1433
+ return _ComposeBoxContainer (
1434
+ body: body, errorBanner: _sendMessageErrorErrorBanner (context));
1413
1435
}
1414
1436
}
0 commit comments