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