Skip to content

Commit c9b80f2

Browse files
authored
fix(ui): fix message input send button not customisable (#2143)
* fix(ui): fix message input send button not customizable * chore: update CHANGELOG.md * chore: remove unused var
1 parent 1ede309 commit c9b80f2

File tree

5 files changed

+277
-57
lines changed

5 files changed

+277
-57
lines changed

packages/stream_chat_flutter/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## Upcoming
2+
3+
- [[#2118]](https://github.com/GetStream/stream-chat-flutter/issues/2118) Fixed message input
4+
buttons not being able to customized.
5+
16
## 9.5.0
27

38
🐞 Fixed

packages/stream_chat_flutter/lib/src/message_input/countdown_button.dart

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ class StreamCountdownButton extends StatelessWidget {
1616

1717
@override
1818
Widget build(BuildContext context) {
19-
return DecoratedBox(
20-
decoration: BoxDecoration(
21-
shape: BoxShape.circle,
22-
color: StreamChatTheme.of(context).colorTheme.disabled,
23-
),
24-
child: SizedBox.square(
25-
dimension: kDefaultMessageInputIconSize,
26-
child: Center(child: Text('$count')),
19+
return Padding(
20+
padding: const EdgeInsets.all(kDefaultMessageInputIconPadding),
21+
child: DecoratedBox(
22+
decoration: BoxDecoration(
23+
shape: BoxShape.circle,
24+
color: StreamChatTheme.of(context).colorTheme.disabled,
25+
),
26+
child: SizedBox.square(
27+
dimension: kDefaultMessageInputIconSize,
28+
child: Center(child: Text('$count')),
29+
),
2730
),
2831
);
2932
}

packages/stream_chat_flutter/lib/src/message_input/stream_message_input.dart

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import 'dart:math';
44
import 'package:desktop_drop/desktop_drop.dart';
55
import 'package:flutter/material.dart';
66
import 'package:flutter/services.dart';
7-
import 'package:photo_manager/photo_manager.dart';
87
import 'package:stream_chat_flutter/platform_widget_builder/src/platform_widget_builder.dart';
98
import 'package:stream_chat_flutter/src/message_input/attachment_button.dart';
109
import 'package:stream_chat_flutter/src/message_input/command_button.dart';
@@ -125,8 +124,10 @@ class StreamMessageInput extends StatefulWidget {
125124
this.hideSendAsDm = false,
126125
this.enableVoiceRecording = false,
127126
this.sendVoiceRecordingAutomatically = false,
128-
this.idleSendButton,
129-
this.activeSendButton,
127+
Widget? idleSendIcon,
128+
@Deprecated("Use 'idleSendIcon' instead") Widget? idleSendButton,
129+
Widget? activeSendIcon,
130+
@Deprecated("Use 'activeSendIcon' instead") Widget? activeSendButton,
130131
this.showCommandsButton = true,
131132
this.userMentionsTileBuilder,
132133
this.maxAttachmentSize = kDefaultMaxAttachmentSize,
@@ -164,7 +165,17 @@ class StreamMessageInput extends StatefulWidget {
164165
)
165166
bool useNativeAttachmentPickerOnMobile = false,
166167
this.pollConfig,
167-
}) : useSystemAttachmentPicker = useSystemAttachmentPicker || //
168+
}) : assert(
169+
idleSendIcon == null || idleSendButton == null,
170+
'idleSendIcon and idleSendButton cannot be used together',
171+
),
172+
idleSendIcon = idleSendIcon ?? idleSendButton,
173+
assert(
174+
activeSendIcon == null || activeSendButton == null,
175+
'activeSendIcon and activeSendButton cannot be used together',
176+
),
177+
activeSendIcon = activeSendIcon ?? activeSendButton,
178+
useSystemAttachmentPicker = useSystemAttachmentPicker || //
168179
useNativeAttachmentPickerOnMobile;
169180

170181
/// The predicate used to send a message on desktop/web
@@ -292,10 +303,18 @@ class StreamMessageInput extends StatefulWidget {
292303
final bool autofocus;
293304

294305
/// Send button widget in an idle state
295-
final Widget? idleSendButton;
306+
final Widget? idleSendIcon;
307+
308+
/// Send button widget in an idle state
309+
@Deprecated("Use 'idleSendIcon' instead")
310+
Widget? get idleSendButton => idleSendIcon;
296311

297312
/// Send button widget in an active state
298-
final Widget? activeSendButton;
313+
final Widget? activeSendIcon;
314+
315+
/// Send button widget in an active state
316+
@Deprecated("Use 'activeSendIcon' instead")
317+
Widget? get activeSendButton => activeSendIcon;
299318

300319
/// Customize the tile for the mentions overlay.
301320
final UserMentionTileBuilder? userMentionsTileBuilder;
@@ -470,7 +489,7 @@ class StreamMessageInput extends StatefulWidget {
470489

471490
/// State of [StreamMessageInput]
472491
class StreamMessageInputState extends State<StreamMessageInput>
473-
with RestorationMixin<StreamMessageInput>, WidgetsBindingObserver {
492+
with RestorationMixin<StreamMessageInput> {
474493
bool get _commandEnabled => _effectiveController.message.command != null;
475494

476495
bool _actionsShrunk = false;
@@ -514,7 +533,6 @@ class StreamMessageInputState extends State<StreamMessageInput>
514533
@override
515534
void initState() {
516535
super.initState();
517-
WidgetsBinding.instance.addObserver(this);
518536
if (widget.messageInputController == null) {
519537
_createLocalController();
520538
} else {
@@ -544,29 +562,6 @@ class StreamMessageInputState extends State<StreamMessageInput>
544562
super.didChangeDependencies();
545563
}
546564

547-
bool _askingForPermission = false;
548-
549-
@override
550-
void didChangeAppLifecycleState(AppLifecycleState state) async {
551-
if (state == AppLifecycleState.resumed &&
552-
_permissionState != null &&
553-
!_askingForPermission) {
554-
_askingForPermission = true;
555-
556-
try {
557-
final newPermissionState = await PhotoManager.requestPermissionExtend();
558-
if (newPermissionState != _permissionState && mounted) {
559-
setState(() {
560-
_permissionState = newPermissionState;
561-
});
562-
}
563-
} catch (_) {}
564-
565-
_askingForPermission = false;
566-
}
567-
super.didChangeAppLifecycleState(state);
568-
}
569-
570565
@override
571566
void didUpdateWidget(covariant StreamMessageInput oldWidget) {
572567
super.didUpdateWidget(oldWidget);
@@ -601,8 +596,6 @@ class StreamMessageInputState extends State<StreamMessageInput>
601596
// ignore: no-empty-block
602597
void _focusNodeListener() {}
603598

604-
PermissionState? _permissionState;
605-
606599
@override
607600
Widget build(BuildContext context) {
608601
final channel = StreamChannel.of(context).channel;
@@ -840,16 +833,16 @@ class StreamMessageInputState extends State<StreamMessageInput>
840833
}
841834

842835
Widget _buildSendButton(BuildContext context) {
843-
if (widget.sendButtonBuilder != null) {
844-
return widget.sendButtonBuilder!(context, _effectiveController);
836+
if (widget.sendButtonBuilder case final builder?) {
837+
return builder(context, _effectiveController);
845838
}
846839

847840
return StreamMessageSendButton(
848841
onSendMessage: sendMessage,
849842
timeOut: _effectiveController.cooldownTimeOut,
850843
isIdle: !widget.validator(_effectiveController.message),
851-
idleSendButton: widget.idleSendButton,
852-
activeSendButton: widget.activeSendButton,
844+
idleSendIcon: widget.idleSendIcon,
845+
activeSendIcon: widget.activeSendIcon,
853846
);
854847
}
855848

@@ -1580,7 +1573,6 @@ class StreamMessageInputState extends State<StreamMessageInput>
15801573
_focusNode?.dispose();
15811574
_onChangedDebounced.cancel();
15821575
_audioRecorderController.dispose();
1583-
WidgetsBinding.instance.removeObserver(this);
15841576
super.dispose();
15851577
}
15861578
}

packages/stream_chat_flutter/lib/src/message_input/stream_message_send_button.dart

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,21 @@ class StreamMessageSendButton extends StatelessWidget {
1515
this.isCommandEnabled = false,
1616
@Deprecated('Will be removed in the next major version')
1717
this.isEditEnabled = false,
18-
this.idleSendButton,
19-
this.activeSendButton,
18+
Widget? idleSendIcon,
19+
@Deprecated("Use 'idleSendIcon' instead") Widget? idleSendButton,
20+
Widget? activeSendIcon,
21+
@Deprecated("Use 'activeSendIcon' instead") Widget? activeSendButton,
2022
required this.onSendMessage,
21-
});
23+
}) : assert(
24+
idleSendIcon == null || idleSendButton == null,
25+
'idleSendIcon and idleSendButton cannot be used together',
26+
),
27+
idleSendIcon = idleSendIcon ?? idleSendButton,
28+
assert(
29+
activeSendIcon == null || activeSendButton == null,
30+
'activeSendIcon and activeSendButton cannot be used together',
31+
),
32+
activeSendIcon = activeSendIcon ?? activeSendButton;
2233

2334
/// Time out related to slow mode.
2435
final int timeOut;
@@ -34,11 +45,19 @@ class StreamMessageSendButton extends StatelessWidget {
3445
@Deprecated('It will be removed in the next major version')
3546
final bool isEditEnabled;
3647

48+
/// The icon to display when the button is idle.
49+
final Widget? idleSendIcon;
50+
3751
/// The widget to display when the button is disabled.
38-
final Widget? idleSendButton;
52+
@Deprecated("Use 'idleSendIcon' instead")
53+
Widget? get idleSendButton => idleSendIcon;
54+
55+
/// The icon to display when the button is active.
56+
final Widget? activeSendIcon;
3957

4058
/// The widget to display when the button is enabled.
41-
final Widget? activeSendButton;
59+
@Deprecated("Use 'activeSendIcon' instead")
60+
Widget? get activeSendButton => activeSendIcon;
4261

4362
/// The callback to call when the button is pressed.
4463
final VoidCallback onSendMessage;
@@ -62,19 +81,25 @@ class StreamMessageSendButton extends StatelessWidget {
6281
);
6382
}
6483

84+
final idleIcon = switch (idleSendIcon) {
85+
final idleIcon? => idleIcon,
86+
_ => const StreamSvgIcon(icon: StreamSvgIcons.sendMessage),
87+
};
88+
89+
final activeIcon = switch (activeSendIcon) {
90+
final activeIcon? => activeIcon,
91+
_ => const StreamSvgIcon(icon: StreamSvgIcons.circleUp),
92+
};
93+
6594
final theme = StreamMessageInputTheme.of(context);
95+
final icon = isIdle ? idleIcon : activeIcon;
6696
final onPressed = isIdle ? null : onSendMessage;
6797
return StreamMessageInputIconButton(
6898
key: const Key('send_button'),
69-
icon: StreamSvgIcon(icon: _sendButtonIcon),
99+
icon: icon,
70100
color: theme.sendButtonColor,
71101
disabledColor: theme.sendButtonIdleColor,
72102
onPressed: onPressed,
73103
);
74104
}
75-
76-
StreamSvgIconData get _sendButtonIcon {
77-
if (isIdle) return StreamSvgIcons.sendMessage;
78-
return StreamSvgIcons.circleUp;
79-
}
80105
}

0 commit comments

Comments
 (0)