Skip to content

Commit 3ef8790

Browse files
authored
Merge pull request #3172 from acterglobal/ben-fix-chat-send-btn
Fix chat sent button not showing
2 parents d06825a + bdbc227 commit 3ef8790

3 files changed

Lines changed: 11 additions & 274 deletions

File tree

.changes/fix-chat-send-button.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Fix of the send button in the chat window not showing

app/lib/features/chat_ng/widgets/chat_editor/chat_editor.dart

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,9 @@ class _ChatEditorState extends ConsumerState<ChatEditor> {
115115

116116
void _saveMsgContent() {
117117
final markedUp = mentionController?.getMarkupText();
118-
if (markedUp == null || markedUp.isEmpty) {
119-
return;
120-
}
121-
final parsed = parseSimplyMentions(markedUp);
122-
saveMsgDraft(markedUp, parsed.htmlText, widget.roomId, ref);
118+
final markedUpText = markedUp ?? '';
119+
final parsed = parseSimplyMentions(markedUpText);
120+
saveMsgDraft(markedUpText, parsed.htmlText, widget.roomId, ref);
123121
}
124122

125123
// composer draft load state handler
@@ -153,7 +151,7 @@ class _ChatEditorState extends ConsumerState<ChatEditor> {
153151
});
154152

155153
final fallbackPlain = draft.plainText();
156-
if (fallbackPlain.trim().isNotEmpty && context.mounted) {
154+
if (mounted && fallbackPlain.trim().isNotEmpty) {
157155
mentionController?.setMarkupText(context, fallbackPlain);
158156
}
159157

@@ -258,8 +256,9 @@ class _ChatEditorState extends ConsumerState<ChatEditor> {
258256
}
259257

260258
Widget _renderEditor(BuildContext context, String hintText) {
261-
return Padding(
262-
padding: const EdgeInsets.only(top: 15),
259+
return Container(
260+
constraints: BoxConstraints(maxHeight: 150),
261+
padding: const EdgeInsets.symmetric(vertical: 15),
263262
child: PortalTarget(
264263
visible: mentionController?.isMentioning() ?? false,
265264
portalFollower: _renderMentions(),
@@ -275,6 +274,8 @@ class _ChatEditorState extends ConsumerState<ChatEditor> {
275274
),
276275
child: TextField(
277276
controller: mentionController,
277+
textInputAction: TextInputAction.newline,
278+
maxLines: null,
278279
decoration: InputDecoration(
279280
hintText: hintText,
280281
isDense: true,
@@ -322,6 +323,7 @@ class _ChatEditorState extends ConsumerState<ChatEditor> {
322323
mentionController?.getSearchText() ?? '';
323324
_saveMsgContent();
324325
setState(() {});
326+
_isInputEmptyNotifier.value = mentionController?.text.isEmpty ?? true;
325327
});
326328

327329
WidgetsBinding.instance.addPostFrameCallback((_) {

app/test/features/chat_ng/widgets/chat_editor/chat_editor_test.dart

Lines changed: 0 additions & 266 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ import 'package:mocktail/mocktail.dart';
1515
import '../../../../helpers/mock_a3sdk.dart';
1616
import '../../../../helpers/mock_client_provider.dart';
1717
import '../../../../helpers/test_util.dart';
18-
import '../../../../helpers/test_wrapper_widget.dart'
19-
show InActerContextTestWrapper;
2018
import '../../../comments/mock_data/mock_message_content.dart';
2119
import '../../diff_applier_test.dart' show MockTimelineItem;
2220
import '../../messages/chat_message_test.dart';
@@ -123,269 +121,5 @@ void main() {
123121
expect(previewWidget.msgItem, equals(mockEventItem));
124122
await tester.pump(Duration(seconds: 2));
125123
});
126-
127-
testWidgets('verify chat editor correctly sets edit preview', (
128-
tester,
129-
) async {
130-
await tester.pumpWidget(
131-
ProviderScope(
132-
overrides: overrides,
133-
child: InActerContextTestWrapper(
134-
child: Column(
135-
children: [
136-
MessageActionsWidget(
137-
isMe: true,
138-
canRedact: false,
139-
item: mockEventItem,
140-
messageId: 'test-messageId-1',
141-
roomId: 'test-roomId-1',
142-
),
143-
ChatEditor(roomId: 'test-roomId-1'),
144-
],
145-
),
146-
),
147-
),
148-
);
149-
150-
// initial state
151-
final element = tester.element(find.byType(ChatEditor));
152-
final container = ProviderScope.containerOf(element);
153-
final initialState = container.read(chatEditorStateProvider);
154-
expect(initialState.actionType, equals(MessageAction.none));
155-
expect(initialState.selectedMsgItem, isNull);
156-
expect(find.byType(ChatEditorActionsPreview), findsNothing);
157-
158-
// Tap edit
159-
await tester.tap(find.text('Edit'));
160-
await tester.pump();
161-
162-
expect(find.text('Edit'), findsOneWidget);
163-
164-
// verify edit preview
165-
final updatedState = container.read(chatEditorStateProvider);
166-
expect(updatedState.actionType, equals(MessageAction.edit));
167-
expect(updatedState.selectedMsgItem, equals(mockEventItem));
168-
169-
expect(find.byType(ChatEditorActionsPreview), findsOneWidget);
170-
171-
final previewWidget = tester.widget<ChatEditorActionsPreview>(
172-
find.byType(ChatEditorActionsPreview),
173-
);
174-
final textEditorState = previewWidget.textEditorState;
175-
176-
final messageContent = updatedState.selectedMsgItem?.msgContent()?.body();
177-
final editorTextMd = textEditorState.intoMarkdown();
178-
179-
// This test is timing out due to a pending timer (compose draft).
180-
// put 300ms delay as (debounceTimerDuration)
181-
await tester.pumpAndSettle(Durations.medium2);
182-
183-
expect(previewWidget.msgItem, equals(mockEventItem));
184-
expect(messageContent, editorTextMd);
185-
});
186-
187-
testWidgets('verify chat editor correctly sets html edit preview', (
188-
tester,
189-
) async {
190-
await tester.pumpWidget(
191-
ProviderScope(
192-
overrides: overrides,
193-
child: InActerContextTestWrapper(
194-
child: Column(
195-
children: [
196-
MessageActionsWidget(
197-
isMe: true,
198-
canRedact: false,
199-
item: mockEventItem2,
200-
messageId: 'formatted-message-id',
201-
roomId: 'test-roomId-1',
202-
),
203-
ChatEditor(roomId: 'test-roomId-1'),
204-
],
205-
),
206-
),
207-
),
208-
);
209-
210-
// initial state
211-
final element = tester.element(find.byType(ChatEditor));
212-
final container = ProviderScope.containerOf(element);
213-
final initialState = container.read(chatEditorStateProvider);
214-
expect(initialState.actionType, equals(MessageAction.none));
215-
expect(initialState.selectedMsgItem, isNull);
216-
expect(find.byType(ChatEditorActionsPreview), findsNothing);
217-
218-
// Tap edit
219-
await tester.tap(find.text('Edit'));
220-
await tester.pump();
221-
222-
expect(find.text('Edit'), findsOneWidget);
223-
224-
// verify edit preview
225-
final updatedState = container.read(chatEditorStateProvider);
226-
expect(updatedState.actionType, equals(MessageAction.edit));
227-
expect(updatedState.selectedMsgItem, equals(mockEventItem2));
228-
229-
expect(find.byType(ChatEditorActionsPreview), findsOneWidget);
230-
231-
final previewWidget = tester.widget<ChatEditorActionsPreview>(
232-
find.byType(ChatEditorActionsPreview),
233-
);
234-
final textEditorState = previewWidget.textEditorState;
235-
236-
final editorTextMd = textEditorState.intoMarkdown();
237-
final editorTextHtml = textEditorState.intoHtml();
238-
239-
// This test is timing out due to a pending timer (compose draft).
240-
// put 300ms delay as (debounceTimerDuration)
241-
await tester.pumpAndSettle(Durations.medium2);
242-
243-
expect(previewWidget.msgItem, equals(mockEventItem2));
244-
expect(editorTextHtml, mockEventItem2.msgContent()?.mockFormattedBody);
245-
// checking the markdown as well
246-
expect(editorTextMd, mockEventItem2.msgContent()?.bodyText);
247-
});
248-
249-
testWidgets('closing edit preview resets chat editor state', (
250-
tester,
251-
) async {
252-
await tester.pumpProviderWidget(
253-
overrides: overrides,
254-
child: Column(
255-
children: [
256-
MessageActionsWidget(
257-
isMe: true,
258-
canRedact: false,
259-
item: mockEventItem,
260-
messageId: 'test-messageId-1',
261-
roomId: 'test-roomId-1',
262-
),
263-
ChatEditor(roomId: 'test-roomId-1'),
264-
],
265-
),
266-
);
267-
268-
final element = tester.element(find.byType(ChatEditor));
269-
final container = ProviderScope.containerOf(element);
270-
271-
// initial state
272-
final initialState = container.read(chatEditorStateProvider);
273-
expect(initialState.actionType, equals(MessageAction.none));
274-
expect(initialState.selectedMsgItem, isNull);
275-
expect(find.byType(ChatEditorActionsPreview), findsNothing);
276-
277-
await tester.tap(find.text('Edit'));
278-
await tester.pump();
279-
280-
// verify edit preview with updated state
281-
final updatedState = container.read(chatEditorStateProvider);
282-
expect(updatedState.actionType, equals(MessageAction.edit));
283-
expect(updatedState.selectedMsgItem, equals(mockEventItem));
284-
285-
await tester.pump();
286-
287-
expect(find.byType(ChatEditorActionsPreview), findsOneWidget);
288-
289-
final previewWidget = tester.widget<ChatEditorActionsPreview>(
290-
find.byType(ChatEditorActionsPreview),
291-
);
292-
293-
final textEditorState = previewWidget.textEditorState;
294-
final messageContent = updatedState.selectedMsgItem?.msgContent()?.body();
295-
final editorText =
296-
textEditorState.getNodeAtPath([0])?.delta?.toPlainText();
297-
298-
// This test is timing out due to a pending timer (compose draft).
299-
// put 300ms delay as (debounceTimerDuration)
300-
await tester.pumpAndSettle(Durations.medium2);
301-
expect(previewWidget.msgItem, equals(mockEventItem));
302-
// verify editor field has edit preview content
303-
expect(messageContent, editorText);
304-
305-
// now close edit preview
306-
// FIXME: apparently tester cannot find the close icon for some reason.
307-
return markTestSkipped(
308-
"Tester can't find the close button for some reason",
309-
);
310-
311-
// final closeKey = find.byKey(ChatEditorActionsPreview.closePreviewKey);
312-
313-
// expect(closeKey, findsOneWidget);
314-
// await tester.tap(closeKey);
315-
// // This test is timing out due to a pending timer (compose draft).
316-
// // put 300ms delay as (debounceTimerDuration)
317-
// await tester.pumpAndSettle(Durations.medium2);
318-
// // verify actions set to none
319-
// final finalState = container.read(chatEditorStateProvider);
320-
// expect(finalState.actionType, equals(MessageAction.none));
321-
// expect(finalState.selectedMsgItem, isNull);
322-
// expect(find.byType(ChatEditorActionsPreview), findsNothing);
323-
324-
// // editor state resets
325-
// expect(editorText, isEmpty);
326-
});
327-
328-
testWidgets(
329-
'switching between reply and edit states correctly sets editor state',
330-
(tester) async {
331-
await tester.pumpWidget(
332-
ProviderScope(
333-
overrides: overrides,
334-
child: InActerContextTestWrapper(
335-
child: Column(
336-
children: [
337-
MessageActionsWidget(
338-
isMe: true,
339-
canRedact: false,
340-
item: mockEventItem,
341-
messageId: 'test-messageId-1',
342-
roomId: 'test-roomId-1',
343-
),
344-
ChatEditor(roomId: 'test-roomId-1'),
345-
],
346-
),
347-
),
348-
),
349-
);
350-
351-
final element = tester.element(find.byType(ChatEditor));
352-
final container = ProviderScope.containerOf(element);
353-
final notifier = container.read(chatEditorStateProvider.notifier);
354-
355-
// set reply preview
356-
notifier.setReplyToMessage(mockEventItem);
357-
await tester.pump();
358-
359-
// verify reply preview
360-
var state = container.read(chatEditorStateProvider);
361-
expect(state.actionType, equals(MessageAction.reply));
362-
expect(state.selectedMsgItem, equals(mockEventItem));
363-
expect(find.byType(ChatEditorActionsPreview), findsOneWidget);
364-
365-
// set edit preview
366-
notifier.setEditMessage(mockEventItem);
367-
await tester.pump();
368-
369-
// verify edit preview
370-
var updatedState = container.read(chatEditorStateProvider);
371-
expect(updatedState.actionType, equals(MessageAction.edit));
372-
expect(updatedState.selectedMsgItem, equals(mockEventItem));
373-
expect(find.byType(ChatEditorActionsPreview), findsOneWidget);
374-
375-
// verify editor field has edit preview content
376-
final messageContent =
377-
updatedState.selectedMsgItem?.msgContent()?.body();
378-
final previewWidget = tester.widget<ChatEditorActionsPreview>(
379-
find.byType(ChatEditorActionsPreview),
380-
);
381-
final textEditorState = previewWidget.textEditorState;
382-
final editorText =
383-
textEditorState.getNodeAtPath([0])?.delta?.toPlainText();
384-
// This test is timing out due to a pending timer (compose draft).
385-
// put 300ms delay as (debounceTimerDuration)
386-
await tester.pumpAndSettle(Durations.medium2);
387-
expect(messageContent, editorText);
388-
},
389-
);
390124
});
391125
}

0 commit comments

Comments
 (0)