🐛 Fix chat newline on desktop

This commit is contained in:
2025-09-27 00:22:43 +08:00
parent a2cc55696f
commit b9dc724f0b

View File

@@ -1,7 +1,5 @@
import "dart:async"; import "dart:async";
import "dart:io";
import "package:easy_localization/easy_localization.dart"; import "package:easy_localization/easy_localization.dart";
import "package:flutter/foundation.dart";
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:flutter/services.dart"; import "package:flutter/services.dart";
import "package:flutter_hooks/flutter_hooks.dart"; import "package:flutter_hooks/flutter_hooks.dart";
@@ -56,10 +54,6 @@ class ChatInput extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final inputFocusNode = useFocusNode(); final inputFocusNode = useFocusNode();
final enterToSend = ref.watch(appSettingsNotifierProvider).enterToSend;
final isMobile = !kIsWeb && (Platform.isAndroid || Platform.isIOS);
void send() { void send() {
onSend.call(); onSend.call();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -67,6 +61,18 @@ class ChatInput extends HookConsumerWidget {
}); });
} }
void insertNewLine() {
final text = messageController.text;
final selection = messageController.selection;
final start = selection.start >= 0 ? selection.start : text.length;
final end = selection.end >= 0 ? selection.end : text.length;
final newText = text.replaceRange(start, end, '\n');
messageController.value = TextEditingValue(
text: newText,
selection: TextSelection.collapsed(offset: start + 1),
);
}
Future<void> handlePaste() async { Future<void> handlePaste() async {
final clipboard = await Pasteboard.image; final clipboard = await Pasteboard.image;
if (clipboard == null) return; if (clipboard == null) return;
@@ -80,32 +86,34 @@ class ChatInput extends HookConsumerWidget {
]); ]);
} }
void handleKeyPress( inputFocusNode.onKeyEvent = (node, event) {
BuildContext context, if (event is! KeyDownEvent) return KeyEventResult.ignored;
WidgetRef ref,
RawKeyEvent event,
) {
if (event is! RawKeyDownEvent) return;
final isPaste = event.logicalKey == LogicalKeyboardKey.keyV; final isPaste = event.logicalKey == LogicalKeyboardKey.keyV;
final isModifierPressed = event.isMetaPressed || event.isControlPressed; final isModifierPressed =
HardwareKeyboard.instance.isMetaPressed ||
HardwareKeyboard.instance.isControlPressed;
if (isPaste && isModifierPressed) { if (isPaste && isModifierPressed) {
handlePaste(); handlePaste();
return; return KeyEventResult.handled;
} }
final enterToSend = ref.read(appSettingsNotifierProvider).enterToSend; final enterToSend = ref.read(appSettingsNotifierProvider).enterToSend;
final isEnter = event.logicalKey == LogicalKeyboardKey.enter; final isEnter = event.logicalKey == LogicalKeyboardKey.enter;
if (isEnter) { if (isEnter) {
if (enterToSend && !isModifierPressed) { if (isModifierPressed) {
send(); insertNewLine();
} else if (!enterToSend && isModifierPressed) { return KeyEventResult.handled;
} else if (enterToSend) {
send(); send();
return KeyEventResult.handled;
} }
} }
}
return KeyEventResult.ignored;
};
return Material( return Material(
elevation: 8, elevation: 8,
@@ -260,59 +268,36 @@ class ChatInput extends HookConsumerWidget {
], ],
), ),
Expanded( Expanded(
child: RawKeyboardListener( child: TextField(
focusNode: FocusNode(), focusNode: inputFocusNode,
onKey: (event) => handleKeyPress(context, ref, event), controller: messageController,
child: TextField( keyboardType: TextInputType.multiline,
focusNode: inputFocusNode, decoration: InputDecoration(
controller: messageController, hintText:
onSubmitted: (chatRoom.type == 1 && chatRoom.name == null)
(enterToSend && isMobile) ? 'chatDirectMessageHint'.tr(
? (_) { args: [
send(); chatRoom.members!
} .map((e) => e.account.nick)
: null, .join(', '),
keyboardType: ],
(enterToSend && isMobile) )
? TextInputType.text : 'chatMessageHint'.tr(args: [chatRoom.name!]),
: TextInputType.multiline, border: InputBorder.none,
textInputAction: TextInputAction.send, isDense: true,
inputFormatters: [ contentPadding: const EdgeInsets.symmetric(
if (enterToSend && !isMobile) horizontal: 12,
TextInputFormatter.withFunction((oldValue, newValue) { vertical: 4,
if (newValue.text.endsWith('\n')) {
return oldValue;
}
return newValue;
}),
],
decoration: InputDecoration(
hintText:
(chatRoom.type == 1 && chatRoom.name == null)
? 'chatDirectMessageHint'.tr(
args: [
chatRoom.members!
.map((e) => e.account.nick)
.join(', '),
],
)
: 'chatMessageHint'.tr(args: [chatRoom.name!]),
border: InputBorder.none,
isDense: true,
contentPadding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 4,
),
counterText:
messageController.text.length > 1024
? '${messageController.text.length}/4096'
: null,
), ),
maxLines: 3, counterText:
minLines: 1, messageController.text.length > 1024
onTapOutside: ? '${messageController.text.length}/4096'
(_) => FocusManager.instance.primaryFocus?.unfocus(), : null,
), ),
maxLines: 3,
minLines: 1,
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
), ),
), ),
IconButton( IconButton(