Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## [Unreleased]

* **Fix**: [430](https://github.com/SimformSolutionsPvtLtd/chatview/pull/430) Added
ChatView.handleImageSelection to use shouldSendImageWithText
parameter with custom trailing actions.
Comment on lines +4 to +5
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changelog entry wording is a bit unclear/grammatically awkward (“Added … to use … parameter …”). Consider rephrasing to something like: “Added ChatView.handleImageSelection to support shouldSendImageWithText when using custom trailingActions.”

Suggested change
ChatView.handleImageSelection to use shouldSendImageWithText
parameter with custom trailing actions.
`ChatView.handleImageSelection` to support `shouldSendImageWithText`
when using custom `trailingActions`.

Copilot uses AI. Check for mistakes.
* **Fix**: [423](https://github.com/SimformSolutionsPvtLtd/chatview/pull/423)
Rendering issue in attached image preview when sending message on web.
* **Feat**: [420](https://github.com/SimformSolutionsPvtLtd/chatview/pull/420) Added support for
Expand Down
13 changes: 12 additions & 1 deletion doc/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -1152,11 +1152,22 @@ PackageStrings.setLocale('es');
```

## Send Image With Message
You can send images along with your messages by enabling the `shouldSendImageWithText` flag in `sendMessageConfig` all the other things will be handled by the package itself. Here's how to do it:
You can send images along with your messages by enabling the `shouldSendImageWithText` option in `sendMessageConfig` and use `ChatView.handleImageSelection` to display an image preview. Here's how to do it:

```dart
sendMessageConfig: SendMessageConfiguration(
shouldSendImageWithText: true, // Enable sending images with text
trailingActions: (context, controller) => [
GalleryActionButton(
icon: Icon(
Icons.photo_rounded,
size: 30,
color: _theme.iconColor,
),
onPressed: (path, replyMessage) {
ChatView.handleImageSelection(context, path!);
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example calls ChatView.handleImageSelection(context, path!) without guarding for path == null (e.g., user cancels picker). Since path is nullable in the action callbacks, the docs should show a null/empty check (as in the example app) to avoid runtime exceptions.

Suggested change
ChatView.handleImageSelection(context, path!);
if (path != null && path.isNotEmpty) {
ChatView.handleImageSelection(context, path);
}

Copilot uses AI. Check for mistakes.
},
Comment on lines +1160 to +1169
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation example is using trailingActions directly on SendMessageConfiguration, but that property is on TextFieldConfiguration (sendMessageConfig.textFieldConfig.trailingActions). As written, the snippet won’t compile and may mislead users.

Suggested change
trailingActions: (context, controller) => [
GalleryActionButton(
icon: Icon(
Icons.photo_rounded,
size: 30,
color: _theme.iconColor,
),
onPressed: (path, replyMessage) {
ChatView.handleImageSelection(context, path!);
},
textFieldConfig: TextFieldConfiguration(
trailingActions: (context, controller) => [
GalleryActionButton(
icon: Icon(
Icons.photo_rounded,
size: 30,
color: _theme.iconColor,
),
onPressed: (path, replyMessage) {
ChatView.handleImageSelection(context, path!);
},
),
],

Copilot uses AI. Check for mistakes.
),
Comment on lines +1162 to +1170
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GalleryActionButton snippet in this code block has mismatched indentation/parentheses and is missing the closing ] / ) needed to end trailingActions and SendMessageConfiguration, so the example won’t compile as-is. Please fix the bracket/parenthesis structure so the snippet is valid Dart.

Suggested change
icon: Icon(
Icons.photo_rounded,
size: 30,
color: _theme.iconColor,
),
onPressed: (path, replyMessage) {
ChatView.handleImageSelection(context, path!);
},
),
icon: Icon(
Icons.photo_rounded,
size: 30,
color: _theme.iconColor,
),
onPressed: (path, replyMessage) {
ChatView.handleImageSelection(context, path!);
},
),
],

Copilot uses AI. Check for mistakes.
),
```

Expand Down
25 changes: 15 additions & 10 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ class _ExampleOneChatScreenState extends State<ExampleOneChatScreen> {
_customSeparatorWidget(separator),
),
sendMessageConfig: SendMessageConfiguration(
shouldSendImageWithText: true,
closeIconColor: _theme.iconColor,
replyTitleColor: _theme.textColor,
replyMessageColor: _theme.textColor,
Expand Down Expand Up @@ -703,16 +704,20 @@ class _ExampleOneChatScreenState extends State<ExampleOneChatScreen> {
),
onPressed: (path, replyMessage) {
if (path?.isEmpty ?? true) return;
_chatController.addMessage(
Message(
id: DateTime.now().millisecondsSinceEpoch.toString(),
message: path!,
createdAt: DateTime.now(),
messageType: MessageType.image,
sentBy: _chatController.currentUser.id,
replyMessage: replyMessage ?? const ReplyMessage(),
),
);
// Uncomment below to send image message directly
// _chatController.addMessage(
// Message(
// id: DateTime.now().millisecondsSinceEpoch.toString(),
// message: path!,
// createdAt: DateTime.now(),
// messageType: MessageType.image,
// sentBy: _chatController.currentUser.id,
// replyMessage: replyMessage ?? const ReplyMessage(),
// ),
// );

// Show Images Preview in Textfield
ChatView.handleImageSelection(context, path!);
},
),
EmojiPickerActionButton(
Expand Down
12 changes: 12 additions & 0 deletions lib/src/widgets/chat_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,18 @@ class ChatView extends StatefulWidget {
return state?._sendMessageKey.currentState?.replyMessage;
}

/// Allows external widgets to add an image to the SendMessageWidget's selection.
static void handleImageSelection(BuildContext context, String imagePath) {
final state = context.findAncestorStateOfType<_ChatViewState>();

assert(
state != null,
'ChatViewState not found. Make sure to use correct context that contains the ChatViewState',
);

state?._sendMessageKey.currentState?.handleImageSelection(imagePath);
}

@override
State<ChatView> createState() => _ChatViewState();
}
Expand Down
32 changes: 16 additions & 16 deletions lib/src/widgets/send_message_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -178,22 +178,7 @@ class SendMessageWidgetState extends State<SendMessageWidget> {
sendMessageConfig: widget.sendMessageConfig,
onRecordingComplete: _onRecordingComplete,
onImageSelected: (images, messageId) {
if (widget.sendMessageConfig
.shouldSendImageWithText) {
if (images.isNotEmpty) {
_selectedImageViewWidgetKey.currentState
?.selectedImages.value = [
...?_selectedImageViewWidgetKey
.currentState?.selectedImages.value,
images
];

FocusScope.of(context)
.requestFocus(_focusNode);
}
} else {
_onImageSelected(images, '');
}
handleImageSelection(images);
},
Comment on lines 180 to 182
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The onImageSelected callback parameter messageId is unused, which triggers the unused_parameter analyzer warning unless it’s named _. Consider changing the callback signature to (imagePath, _) (and renaming images to imagePath for clarity) before calling handleImageSelection(imagePath).

Copilot uses AI. Check for mistakes.
),
],
Expand Down Expand Up @@ -284,6 +269,21 @@ class SendMessageWidgetState extends State<SendMessageWidget> {
}
}

/// Handles image selection and focus logic. Can be called externally to add images to the selection.
void handleImageSelection(String images) {
if (widget.sendMessageConfig.shouldSendImageWithText) {
if (images.isNotEmpty) {
_selectedImageViewWidgetKey.currentState?.selectedImages.value = [
...?_selectedImageViewWidgetKey.currentState?.selectedImages.value,
images
];
FocusScope.of(context).requestFocus(_focusNode);
}
} else {
_onImageSelected(images, '');
Comment on lines +273 to +283
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleImageSelection takes a single image path, but the parameter is named images, which is misleading given the surrounding code uses a list of selected images. Renaming the parameter to imagePath (and updating internal references) would reduce confusion.

Suggested change
void handleImageSelection(String images) {
if (widget.sendMessageConfig.shouldSendImageWithText) {
if (images.isNotEmpty) {
_selectedImageViewWidgetKey.currentState?.selectedImages.value = [
...?_selectedImageViewWidgetKey.currentState?.selectedImages.value,
images
];
FocusScope.of(context).requestFocus(_focusNode);
}
} else {
_onImageSelected(images, '');
void handleImageSelection(String imagePath) {
if (widget.sendMessageConfig.shouldSendImageWithText) {
if (imagePath.isNotEmpty) {
_selectedImageViewWidgetKey.currentState?.selectedImages.value = [
...?_selectedImageViewWidgetKey.currentState?.selectedImages.value,
imagePath
];
FocusScope.of(context).requestFocus(_focusNode);
}
} else {
_onImageSelected(imagePath, '');

Copilot uses AI. Check for mistakes.
}
}

double get _bottomPadding => (!kIsWeb && Platform.isIOS)
? (_focusNode.hasFocus
? bottomPadding1
Expand Down
Loading